]> git.mxchange.org Git - friendica.git/blob - bin/composer.phar
"For you" now respects the "notify new posts" setting
[friendica.git] / bin / composer.phar
1 #!/usr/bin/env php
2 <?php
3 /*
4  * This file is part of Composer.
5  *
6  * (c) Nils Adermann <naderman@naderman.de>
7  *     Jordi Boggiano <j.boggiano@seld.be>
8  *
9  * For the full copyright and license information, please view
10  * the license that is located at the bottom of this file.
11  */
12
13 // Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264
14 if (extension_loaded('apc') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN) && filter_var(ini_get('apc.cache_by_default'), FILTER_VALIDATE_BOOLEAN)) {
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 \8d\96\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.php3k\0\0¼àVb3k\0\0y[£\13¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.phpÖ\1a\0\0¼àVbÖ\1a\0\0ß\f\86\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpä\13\0\0¼àVbä\13\0\0xw\0ܤ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpØ\ 2\0\0¼àVbØ\ 2\0\0ö÷;\87¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpä\14\0\0¼àVbä\14\0\0Õ\15­\7f¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÚ\v\0\0¼àVbÚ\v\0\0Ý\10\88ˤ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.php\\19\0\0¼àVb\\19\0\0{\8d9d¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Command/CheckPlatformReqsCommand.php}\ f\0\0¼àVb}\ f\0\0\1c0Û¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php½\ 5\0\0¼àVb½\ 5\0\0°\ 2\b\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php»Q\0\0¼àVb»Q\0\0^¼ÿȤ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.phpe;\0\0¼àVbe;\0\0'\98À\ 5¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.phpø\ 2\0\0¼àVbø\ 2\0\0ªe\11á¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.php]P\0\0¼àVb]P\0\0MTõj¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.phpã\v\0\0¼àVbã\v\0\0© ]\86¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.php\1c \0\0¼àVb\1c \0\0?ìç\11¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/FundCommand.php+
28 \0\0¼àVb+
29 \0\0ð\19`ó¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpÅ       \0\0¼àVbÅ \0\0©O:ü¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.phpú\ e\0\0¼àVbú\ e\0\0Ï9mU¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.php:U\0\0¼àVb:U\0\0\88\8a»â¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.php"\15\0\0¼àVb"\15\0\0®ò¤\81¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.phpò\ e\0\0¼àVbò\ e\0\0´\18È\1c¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php\ f\f\0\0¼àVb\ f\f\0\0ا\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.php\12\ 3\0\0¼àVb\12\ 3\0\0_¤éS¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.phpß\18\0\0¼àVbß\18\0\0ì:/|¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php¨)\0\0¼àVb¨)\0\0µDàÿ¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php±\ f\0\0¼àVb±\ f\0\0\99Ò-Ť\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.php¯\ 5\0\0¼àVb¯\ 5\0\0?=\10Ѥ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpT      \0\0¼àVbT \0\0\7f±¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.php\94D\0\0¼àVb\94D\0\0\v\9a¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.phpp\82\0\0¼àVbp\82\0\0¼¨ìÛ¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php%\16\0\0¼àVb%\16\0\0\8e\14ÞÚ¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php
30 \ e\0\0¼àVb
31 \ e\0\0y\92°ø¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.phpë#\0\0¼àVbë#\0\03<&\0¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.phpe\14\0\0¼àVbe\14\0\0ï\ 3
32 ²¤\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.php}\v\0\0¼àVb}\v\0\0\8f\9a§ó¤\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phpø$\0\0¼àVbø$\0\0\19öÙú¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0¼àVb\ e\ 2\0\0³\f[/¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php²\14\0\0¼àVb²\14\0\0Gd=\9e¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.php[8\0\0¼àVb[8\0\0,&M\8a¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php0\ 6\0\0¼àVb0\ 6\0\0\9aÒ¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.php6\10\0\0¼àVb6\10\0\0à\95\f\9e¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 5\17\0\0¼àVb\ 5\17\0\0Þ       \b¼¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.php´\ 3\0\0¼àVb´\ 3\0\0n±ðã¤\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0¼àVbC\ 2\0\0´\õ*¤\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0¼àVb÷\ 2\0\0ïÎà÷¤\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0¼àVbý\ 2\0\0\193#\86¤\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0¼àVbÓ\0\0\0Ùâ&ä¤\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0¼àVb¹\ 1\0\0&¢e
33 ¤\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0¼àVbI\ 2\0\0FûÂɤ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.php'\ 4\0\0¼àVb'\ 4\0\0Qúɯ¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0¼àVb­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.phpü"\0\0¼àVbü"\0\0l\9e\83Ƥ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.php÷\17\0\0¼àVb÷\17\0\0K\8eX\8b¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0¼àVb\83\ 4\0\0åVP\84¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php:\19\0\0¼àVb:\19\0\0=$\19¨¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php\17\ 5\0\0¼àVb\17\ 5\0\0\r\11NS¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.php¨
34 \0\0¼àVb¨
35 \0\0XÏé¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.php\83\1f\0\0¼àVb\83\1f\0\0ù\15c\1a¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\11\ 6\0\0¼àVb\11\ 6\0\0\9bCü$¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0¼àVbi\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpÞ\ 6\0\0¼àVbÞ\ 6\0\0ã\983¼¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.php\ 4\ 4\0\0¼àVb\ 4\ 4\0\07§¹!¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.phpF:\0\0¼àVbF:\0\0\10\93\89¨¤\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\99\ 1\0\0¼àVb\99\ 1\0\0X\12g6¤\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpk\b\0\0¼àVbk\b\0\0\10tÍP¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.phpÔ\13\0\0¼àVbÔ\13\0\0\99\8d^G¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.phpÁ      \0\0¼àVbÁ \0\0ÖÞw7¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0¼àVbÌ\0\0\0¯à¨¿¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.php_\15\0\0¼àVb_\15\0\0\fóøþ¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0¼àVbÊ\ 1\0\0gs!l¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0¼àVbÑ\0\0\0\9c¿¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.php>\1c\0\0¼àVb>\1c\0\0tÀU\98¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
36 \ 1\0\0¼àVb
37 \ 1\0\0.-\1e\8b¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php\89\v\0\0¼àVb\89\v\0\0È¢ñç¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php\ 37\0\0¼àVb\ 37\0\0âh#Ȥ\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0¼àVbó\ 6\0\0Í\11y\86¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php \b\0\0¼àVb \b\0\0ß`\9aö¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpJ\15\0\0¼àVbJ\15\0\0)4\ 4פ\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpq\e\0\0¼àVbq\e\0\0y5+\ 5¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.php\9e\a\0\0¼àVb\9e\a\0\0Öüñ9¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpä\0\0\0¼àVbä\0\0\0B"2(¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9f\a\0\0¼àVb\9f\a\0\0\19\e\19\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpN\14\0\0¼àVbN\14\0\0 â\97\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpâ\0\0\0¼àVbâ\0\0\0\ 4+«r¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0¼àVb=\ 2\0\0ZÎÈÞ¤\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0¼àVbÔ\0\0\0`§ôö¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php\98\16\0\0¼àVb\98\16\0\0ö\9f\86\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0¼àVb§\ 4\0\0W$;á¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.phpx\15\0\0¼àVbx\15\0\0\82MÚH¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0¼àVb \ 2\0\0±\99jï¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.phpL7\0\0¼àVbL7\0\0+[¸\8c¤\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0¼àVb©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0¼àVbv\0\0\0wZ8S¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0¼àVbf\0\0\0ËíM\9d¤\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.php#>\0\0¼àVb#>\0\0\ 2^¡4¤\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\99\12\0\0¼àVb\99\12\0\0Y\85%\f¤\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php½\ 6\0\0¼àVb½\ 6\0\0*Äx\87¤\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php\11\19\0\0¼àVb\11\19\0\0\88\8fÍ\11¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0¼àVbì\ 5\0\0\0Õ\9d\ e¤\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0¼àVbÀ\ 4\0\0F`sʤ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.phpD£\0\0¼àVbD£\0\0\10{¶Ï¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php\ 1\12\0\0¼àVb\ 1\12\0\0a·Á\10¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0¼àVbË\0\0\0À5\9a¨¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php*\17\0\0¼àVb*\17\0\0Í\96\85ª¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0¼àVb\ e\ 6\0\0lÔzi¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0¼àVbÞ\0\0\0ì\9f@G¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0¼àVbã\ 2\0\0^\83\93ʤ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php"\14\0\0¼àVb"\14\0\0?¦@¬¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.phpÊ\a\0\0¼àVbÊ\a\0\0Ùti·¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0¼àVb+\ 5\0\0À·M}¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0¼àVbe\ 3\0\0;° \1a¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0¼àVb¸\ 1\0\0dbØs¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpø\f\0\0¼àVbø\f\0\0\95\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0¼àVb¢\a\0\0È\82¶Ñ¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php¡\ 6\0\0¼àVb¡\ 6\0\0¤õÏܤ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0¼àVb\1d\ 6\0\0*0@P¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php:\a\0\0¼àVb:\a\0\0\82´UV¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.phpJ\15\0\0¼àVbJ\15\0\0\8a\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.phpW\ 6\0\0¼àVbW\ 6\0\0uüb\8c¤\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.phpv4\0\0¼àVbv4\0\0\18­¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0¼àVb\\ 1\0\0.Xóܤ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.phpí\17\0\0¼àVbí\17\0\0\98J¸X¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php    \ 2\0\0¼àVb \ 2\0\0yY+¦¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpæ\ 5\0\0¼àVbæ\ 5\0\0U`\eƤ\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.phpÕ\f\0\0¼àVbÕ\f\0\0q^Z\90¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0¼àVb\a\ 1\0\0ñ´>\v¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0¼àVb\96\ 6\0\0v,ÝФ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0¼àVb\1f\ 1\0\0\8bSZ0¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpr\ 3\0\0¼àVbr\ 3\0\03\91Mh¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php
38 \ 5\0\0¼àVb
39 \ 5\0\0&ðm(¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php8\ 6\0\0¼àVb8\ 6\0\0Fx'M¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.phpX\ 5\0\0¼àVbX\ 5\0\0¤k\9d\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php\b\ e\0\0¼àVb\b\ e\0\0r\97F«¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Comparer/Comparer.php½\b\0\0¼àVb½\b\0\0¡fK}¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.php¦\a\0\0¼àVb¦\a\0\0p[\ 3Ö¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.php\e\ 2\0\0¼àVb\e\ 2\0\0Î\12«>¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpb\f\0\0¼àVbb\f\0\0s\95°\9b¤\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0¼àVb\88\ 5\0\0å¶Y«¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0¼àVb\82\ 1\0\0\ eé~\8b¤\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0¼àVbd\ 1\0\0¤ôLn¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0¼àVb\82\ 1\0\0ób`ý¤\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0¼àVbi\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0¼àVbX\ 1\0\0\ 2}`y¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.phpô\1e\0\0¼àVbô\1e\0\0\11h°ª¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0¼àVbE\ 2\0\0xb\13¾¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0¼àVbù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0¼àVb²\0\0\0¦}úΤ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.phpÆ\1a\0\0¼àVbÆ\1a\0\0\99£ã\9b¤\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.phpâA\0\0¼àVbâA\0\0\1c\91É\98¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php\11#\0\0¼àVb\11#\0\0»ÀÎí¤\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0¼àVbÉ\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php\\b\0\0¼àVb\\b\0\0xåp¨¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f        \0\0¼àVb\1f \0\0      _\80ø¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0¼àVb\11\ 5\0\0\ 2\8eÎ_¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0¼àVb¹\ 3\0\0"maV¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpÏ#\0\0¼àVbÏ#\0\0@»å'¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.php¥\ 5\0\0¼àVb¥\ 5\0\0ô´\16à¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.php\9a\ e\0\0¼àVb\9a\ e\0\0ô¥×¥¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0¼àVbW\0\0\0æ_¨1¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0¼àVb\97\0\0\0ûOâ>¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0¼àVb\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0¼àVbâ\ 2\0\0³ÆÇW¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpö\0\0\0¼àVbö\0\0\0á1=z¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0¼àVbô\0\0\0)'*ؤ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.php¨$\0\0¼àVb¨$\0\03 :\90¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Plugin/PreCommandRunEvent.phpõ\ 1\0\0¼àVbõ\ 1\0\0:ðd\1e¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0¼àVb`\ 2\0\0\09-Τ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0¼àVb\1e\ 5\0\0'.³è¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php©\ e\0\0¼àVb©\ e\0\0Â\92/Ƥ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.phpí\b\0\0¼àVbí\b\0\0q9OS¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.phpU\10\0\0¼àVbU\10\0\0{<\9f\16¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php5U\0\0¼àVb5U\0\0¾øU&¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0¼àVb;\b\0\0¤¯S\1f¤\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0¼àVb\85\0\0\0±\9f_\1c¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.phpo\ 5\0\0¼àVbo\ 5\0\0åè¼\9e¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0¼àVb£\0\0\0/ö~>¤\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0¼àVb£\0\0\0V
40 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0¼àVb\87\0\0\0\18£9p¤\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0¼àVbn\0\0\0à\93ë\98¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpi\ 3\0\0¼àVbi\ 3\0\0\82\ 1\b\96¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.php¬\ f\0\0¼àVb¬\ f\0\0ÐU\91\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpH\ 5\0\0¼àVbH\ 5\0\0\vÁÚ\8b¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0¼àVbÄ\ 1\0\0:T*ɤ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpë\ 6\0\0¼àVbë\ 6\0\0åÄLi¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.php®        \0\0¼àVb® \0\0\99ÖÛú¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0¼àVb& \0\0òUb\b¤\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0¼àVbq\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0¼àVbq\ 1\0\0fºTò¤\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\83\16\0\0¼àVb\83\16\0\0ð\90\93\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0¼àVb°\ 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¼àVb\92\ 1\0\0o\93\8aä\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.php¥\16\0\0¼àVb¥\16\0\0ç\ f|5¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php)!\0\0¼àVb)!\0\0À(\87ߤ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.phpa\13\0\0¼àVba\13\0\0lÂéÔ¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0¼àVbÛ\ 1\0\0\92\11âÁ¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.phpM\v\0\0¼àVbM\v\0\0<(;\8c¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0¼àVbo\0\0\0pÕ«ª¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.php~ \0\0¼àVb~ \0\0Ebºå¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php´\13\0\0¼àVb´\13\0\0Å\ 2\86\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpë\ 5\0\0¼àVbë\ 5\0\0\9c´½X¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.php\96\14\0\0¼àVb\96\14\0\0ÂGîŤ\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.php\834\0\0¼àVb\834\0\0:0G\b¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.php}*\0\0¼àVb}*\0\0d\8fer¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpå\ 5\0\0¼àVbå\ 5\0\0@)\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.php)\13\0\0¼àVb)\13\0\0Nÿü\ 6¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.phpù        \0\0¼àVbù \0\0&½tÙ¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php\9e\1c\0\0¼àVb\9e\1c\0\0â]Ñ\98¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
41 \0\0¼àVbæ
42 \0\0eׯ-¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0¼àVb÷\ 2\0\0ÇX[\89¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.php\8e-\0\0¼àVb\8e-\0\0÷ï\rì¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/VersionCacheInterface.php\94\0\0\0¼àVb\94\0\0\0A?Rï¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\r\ 3\0\0¼àVb\r\ 3\0\0¤3¶¢¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0¼àVb\89\ 1\0\0\91/sï¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0¼àVbW\0\0\0£VZt¤\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpº\ 4\0\0¼àVbº\ 4\0\0ò\9d»¤¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0¼àVb\9c\0\0\0§ÿÉ\r¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0¼àVbP\ 4\0\0\87\8f\ 4¶¤\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9c\ 1\0\0¼àVb\9c\ 1\0\0ze\83\8e¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpH\a\0\0¼àVbH\a\0\0c\vlB¤\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0¼àVbË\ 3\0\0>zx\96¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php%\15\0\0¼àVb%\15\0\0N,vÕ¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0¼àVb±\ 4\0\0­½øؤ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.phpà\15\0\0¼àVbà\15\0\0¯º`\97¤\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php\7f\ 5\0\0¼àVb\7f\ 5\0\0ÂV\90\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.php`/\0\0¼àVb`/\0\0ÓJ\89\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.phpø0\0\0¼àVbø0\0\0Zð\     ¤\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.phpz\r\0\0¼àVbz\r\0\0\13\f!Ò¤\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.phpó\ e\0\0¼àVbó\ e\0\0^\1e  '¤\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Util/Hg.php¼\a\0\0¼àVb¼\a\0\0\83]\18\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.phph\ 2\0\0¼àVbh\ 2\0\0;F\b\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.phpr\14\0\0¼àVbr\14\0\0\e\9c´R¤\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Util/PackageSorter.phpÜ\ 5\0\0¼àVbÜ\ 5\0\0w\88Ôâ¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php¶2\0\0¼àVb¶2\0\0ßÑvT¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpû\ 4\0\0¼àVbû\ 4\0\0ñ®\8f\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.php\87\r\0\0¼àVb\87\r\0\0X\90§3¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.phpRr\0\0¼àVbRr\0\0à¹\96\10¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpè\ 2\0\0¼àVbè\ 2\0\0¿5ѳ¤\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0¼àVb\ 3\ 1\0\0¾7
43 ñ¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.phpú\ f\0\0¼àVbú\ f\0\00K\9a\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php'\14\0\0¼àVb'\14\0\0ôS,,¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpH
44 \0\0¼àVbH
45 \0\0Ì\ 6Ú\ f¤\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Url.php\9e\a\0\0¼àVb\9e\a\0\0qµkQ¤\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Zip.php¯\ 5\0\0¼àVb¯\ 5\0\0ti¸Î¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.phpð\ 1\0\0¼àVbð\ 1\0\0zÓf~¤\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0¼àVb¹\ 1\0\0\15I}\9c¤\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.php¡4\0\0¼àVb¡4\0\0Þs\85\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0¼àVbð\ f\0\0\81GÐà¤\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.jsonM\9d\0\0¼àVbM\9d\0\0U|Û\b¤\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.json¸\v\0\0¼àVb¸\v\0\0Â4DC¤\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.json\14¾\0\0¼àVb\14¾\0\0eÇõ̤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Resources/bin/hiddeninput.exe\0$\0\0¼àVb\0$\0\0\95\8d¥v¤\ 1\0\0\0\0\0\0D\0\0\0vendor/symfony/polyfill-mbstring/Resources/mb_convert_variables.php8?\ 3\0\0¼àVb?\ 3\0\0ò\16ï ¤\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php+X\0\0¼àVb+X\0\0«­yX¤\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.phpä"\0\0¼àVbä"\0\0\90¤Ê¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpØ\a\0\0¼àVbØ\a\0\0¦Ú-:¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0¼àVbZ\b\0\0»w\ 4\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpé\0\0\0¼àVbé\0\0\0RÛÔe¤\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpÏ\b\0\0¼àVbÏ\b\0\0<\8eUî¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\8f\a\0\0¼àVb\8f\a\0\0¿N\ f\95¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0¼àVbü\0\0\0±Q\aµ¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpÜ\r\0\0¼àVbÜ\r\0\0\9dɤ\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¶\ e\0\0¼àVb¶\ e\0\0·Ô;ݤ\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php·\1e\0\0¼àVb·\1e\0\0c\93q\80¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ 1\1c\0\0¼àVb\ 1\1c\0\0\7fb{<¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php°\ 1\0\0¼àVb°\ 1\0\0\a!\0Ȥ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0¼àVbÅ\ 2\0\0ÒxÛ\¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0¼àVb\12\ 3\0\0á\162é¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0¼àVbz\ 2\0\0³,îL¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0¼àVbÔ\ 1\0\0È÷ L¤\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0¼àVbf\0\0\0¡ABª¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0¼àVb¦\0\0\0Ö̽Z¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0¼àVb¦\0\0\0\13Ë×H¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0¼àVb\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¼àVb\96\0\0\0Ùí,6¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php3\ e\0\0¼àVb3\ e\0\0\11à\10פ\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0¼àVb\8c\ 1\0\0òññÀ¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpF\10\0\0¼àVbF\10\0\0\1d𦴤\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\84\ 1\0\0¼àVb\84\ 1\0\0÷½\10\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.php@\ 5\0\0¼àVb@\ 5\0\0G¨ýU¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpy\b\0\0¼àVby\b\0\0Ì8ÆФ\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpw\ 5\0\0¼àVbw\ 5\0\0\ 1\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.phpð\1e\0\0¼àVbð\1e\0\0ÔÈ\16\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpd\ 4\0\0¼àVbd\ 4\0\0§×,¸¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php©\a\0\0¼àVb©\a\0\0Õ'\83±¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpå\0\0\0¼àVbå\0\0\0\1f\8a \18¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÊ\a\0\0¼àVbÊ\a\0\0áÏW"¤\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0¼àVbc\ 1\0\0\ 6Ìø\83¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÓ       \0\0¼àVbÓ \0\0©w\82\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phpc%\0\0¼àVbc%\0\0C\e&w¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.phpY\e\0\0¼àVbY\e\0\0R!\8f\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpM\14\0\0¼àVbM\14\0\0ü\8d\b\87¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.php[\1d\0\0¼àVb[\1d\0\0¯6}ñ¤\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.php\95
46 \0\0¼àVb\95
47 \0\0\0]~R¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.php¼*\0\0¼àVb¼*\0\0fêý!¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\80\ 3\0\0¼àVb\80\ 3\0\0\8b\83[\ e¤\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\ e\f\0\0¼àVb\ e\f\0\0\9b\99¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÊ\0\0\0¼àVbÊ\0\0\0az\1f\1c¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php 
48 \0\0¼àVb 
49 \0\0_ÍI"¤\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\ 1\16\0\0¼àVb\ 1\16\0\0ªèB-¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php)\v\0\0¼àVb)\v\0\0¥Ñ\ 6\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.php£\v\0\0¼àVb£\v\0\0\13f¡?¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\12\ 6\0\0¼àVb\12\ 6\0\0D\r£\ 6¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\98\0\0\0¼àVb\98\0\0\0­\ fO°¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\86\19\0\0¼àVb\86\19\0\0¤U)¤¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php£\ 3\0\0¼àVb£\ 3\0\0ÆB\8c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\14\f\0\0¼àVb\14\f\0\0\¢Ü=¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\99\ 6\0\0¼àVb\99\ 6\0\0{\8a\9cþ¤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0¼àVb)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php-    \0\0¼àVb- \0\0ghT\9b¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.php_\ 1\0\0¼àVb_\ 1\0\0\8b >P¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.php±\a\0\0¼àVb±\a\0\0nì!f¤\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpà\0\0\0¼àVbà\0\0\0\87\86Æʤ\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÉ\ 3\0\0¼àVbÉ\ 3\0\0\990ïf¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\98  \0\0¼àVb\98 \0\00p\ 4\b¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\17\ 3\0\0¼àVb\17\ 3\0\0\0ì\ 6\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.php\9b\ 6\0\0¼àVb\9b\ 6\0\0.¡îî¤\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpv
50 \0\0¼àVbv
51 \0\0\8b²WP¤\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpè\ 2\0\0¼àVbè\ 2\0\0/\1dÔ\8f¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.phpΠ    \0\0¼àVbΠ\0\0lF\ f\10¤\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpã\ f\0\0¼àVbã\ f\0\0\89Á\8eå¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php\\ 5\0\0¼àVb\\ 5\0\0wפ\ 4¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÏ\ 3\0\0¼àVbÏ\ 3\0\0&nÅѤ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.phpÛ\1f\0\0¼àVbÛ\1f\0\0§ðcä¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÏ\ 5\0\0¼àVbÏ\ 5\0\0s\9e9i¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.php¨\ 6\0\0¼àVb¨\ 6\0\0\7f<\9c\95¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0¼àVbt\ 1\0\0=\0hܤ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.php+\ 3\0\0¼àVb+\ 3\0\0.À=©¤\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.php°\1d\0\0¼àVb°\1d\0\0^æ*ñ¤\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.phpýG\0\0¼àVbýG\0\0¿zL\1d¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\96\ 1\0\0¼àVb\96\ 1\0\0i\89æô¤\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0¼àVb\98\ 1\0\0-
52 d2¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0¼àVb\ 2\ 1\0\0®+Ãê¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.php\f\a\0\0¼àVb\f\a\0\04ç$¤¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpW\ 2\0\0¼àVbW\ 2\0\0?àèK¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php»\16\0\0¼àVb»\16\0\0+a&\11¤\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0¼àVb~\0\0\0ë¨oâ¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\9a\ 1\0\0¼àVb\9a\ 1\0\0\81ñJÀ¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\98\ 1\0\0¼àVb\98\ 1\0\0nöêؤ\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php$3\0\0¼àVb$3\0\0Eë×£¤\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php5\12\0\0¼àVb5\12\0\0\8aÁ*V¤\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0¼àVb\ 3\ 1\0\0ĹBV¤\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpx\b\0\0¼àVbx\b\0\0~ò"\7f¤\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpN\ 5\0\0¼àVbN\ 5\0\0'\80³\88¤\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0¼àVb)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0¼àVbi\0\0\0$ ÿ\9b¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0¼àVb¼\ 1\0\0pí\¶¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0¼àVb\87\ 1\0\0\80ü#Ѥ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0¼àVb¦\0\0\0jÙwM¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.phpM4\0\0¼àVbM4\0\0ãz_\a¤\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0¼àVb)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.phpò\ 5\0\0¼àVbò\ 5\0\0~3\9f\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0¼àVb\\v\0\0h\19\88\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\83\19\0\0¼àVb\83\19\0\0kM Þ¤\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php\9b\ 3\0\0¼àVb\9b\ 3\0\0M\aþ\e¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php2\a\0\0¼àVb2\a\0\0\83\80D)¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\14\a\0\0¼àVb\14\a\0\0¦äàO¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0¼àVbô\a\0\0Þdè;¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8d\ 3\0\0¼àVb\8d\ 3\0\0¾ü\9cµ¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php#\ 3\0\0¼àVb#\ 3\0\0\16°\1fΤ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php{\ 3\0\0¼àVb{\ 3\0\0\80ÚùY¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0¼àVb\84\0\0\0½¾s\9c¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¬\ 2\0\0¼àVb¬\ 2\0\0w\1e\18\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0¼àVb\84\0\0\0\1cGz-¤\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0¼àVb)\ 1\0\0x\1f§e¤\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpº\ 2\0\0¼àVbº\ 2\0\0\98þ\15\98¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0¼àVb\a\ 6\0\0i¥:Ť\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpf\ 4\0\0¼àVbf\ 4\0\0DÞcj¤\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 3\ f\0\0¼àVb\ 3\ f\0\0§;M)¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0¼àVbÍ\ 1\0\0\p4\86¤\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.phpc.\0\0¼àVbc.\0\0:\885g¤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpL\ 5\0\0¼àVbL\ 5\0\0jÍ9פ\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php]\ 2\0\0¼àVb]\ 2\0\0ÎoÅƤ\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpx\ 2\0\0¼àVbx\ 2\0\0\ fô\ 3\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpî\ 1\0\0¼àVbî\ 1\0\0üÍ\9d\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpí\ 5\0\0¼àVbí\ 5\0\0n\ 5õH¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php#\ 6\0\0¼àVb#\ 6\0\0G?T½¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpZ\ 2\0\0¼àVbZ\ 2\0\0(\1a&ø¤\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0¼àVb5\ 2\0\0\9aí\1f\14¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0¼àVbr\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÂ\ 2\0\0¼àVbÂ\ 2\0\0\1c\8f㯤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php*\ 5\0\0¼àVb*\ 5\0\0\ 2\8c\9e\9d¤\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÐ\ 1\0\0¼àVbÐ\ 1\0\0\12\82\b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\ f   \0\0¼àVb\ f \0\0O}Cä¤\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpe\ 2\0\0¼àVbe\ 2\0\0\9f\92áé¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php+\ 6\0\0¼àVb+\ 6\0\0õÝË ¤\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0¼àVb)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.php>\v\0\0¼àVb>\v\0\0_~u\f¤\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpq\ 4\0\0¼àVbq\ 4\0\0·Ó\8a\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.php\ 6\ 3\0\0¼àVb\ 6\ 3\0\0þ\0íù¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/polyfill-ctype/Ctype.phpH   \0\0¼àVbH \0\0³\9dÕݤ\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/polyfill-ctype/LICENSE)\ 4\0\0¼àVb)\ 4\0\0´`e0¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/polyfill-ctype/bootstrap.phpú\ 4\0\0¼àVbú\ 4\0\0\15|p:¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0¼àVb)\ 4\0\0\1f\93\ª¤\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.php~G\0\0¼àVb~G\0\0úì¡T¤\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php÷T\0\0¼àVb÷T\0\0ß2ª?¤\ 1\0\0\0\0\0\0F\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpã\17\0\0¼àVbã\17\0\0öy_\95¤\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpîU\0\0¼àVbîU\0\0`þ8Q¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php\ 3\e\0\0¼àVb\ 3\e\0\0\11þJ¾¤\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0¼àVbf\0\0\0]ö>T¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0¼àVb¨\0\0\0ÐÀ+_¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0¼àVb\94\0\0\0 ³ãñ¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0¼àVbx\ 3\0\0¨Ìzy¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0¼àVb\1f\ 4\0\0\7fï\ e«¤\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0¼àVb\98\0\0\0¢\eØ:¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9c\ 4\0\0¼àVb\9c\ 4\0\0\1eçÁ̤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0¼àVb)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpÍ\ 4\0\0¼àVbÍ\ 4\0\0í\ 50ã¤\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpù\ 3\0\0¼àVbù\ 3\0\0c¶ßĤ\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php¸\a\0\0¼àVb¸\a\0\0xÓ,§¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0¼àVbD\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.php7\b\0\0¼àVb7\b\0\0bÜp\84¤\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.phpi\f\0\0¼àVbi\f\0\0Ó
53  Ä¤\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php R\0\0¼àVb R\0\0×Ó¥¹¤\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpá
54 \0\0¼àVbá
55 \0\0ñ6I\95¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpJ\ 6\0\0¼àVbJ\ 6\0\0\ 6{ñC¤\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0¼àVb"\ 4\0\0a\83sy¤\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.phpk\ 1\0\0¼àVbk\ 1\0\0Zù¶Ã¤\ 1\0\0\0\0\0\05\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php62\0\0¼àVb62\0\0\1128ˤ\ 1\0\0\0\0\0\00\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php#\11\0\0¼àVb#\11\0\0Úá@,¤\ 1\0\0\0\0\0\0;\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php%\ 1\0\0¼àVb%\ 1\0\0`a\84\ 1\0\0\0\0\0\04\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php>\0\0\0¼àVb>\0\0\0ÿq\9f\9f¤\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0¼àVb \ 4\0\0ºç\ 6©¤\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0¼àVbñ\ 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¼àVb¡ \0\0\86wÌl¤\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php\83
56 \0\0¼àVb\83
57 \0\0\9e¸=\9a¤\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.phpÁ\r\0\0¼àVbÁ\r\0\0\96PFF¤\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php¼\ 1\0\0¼àVb¼\ 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¼àVb\\ 3\0\0_\7f}ý¤\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.phpà\f\0\0¼àVbà\f\0\0ë\92_\94¤\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.phps\14\0\0¼àVbs\14\0\0d\ 5\vÞ¤\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php\83       \0\0¼àVb\83 \0\0e\90\f¨¤\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php·\11\0\0¼àVb·\11\0\0%l¬ö¤\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php& \0\0¼àVb& \0\078÷¬¤\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.phpz\ 4\0\0¼àVbz\ 4\0\0ùfÅ~¤\ 1\0\0\0\0\0\0X\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.phpa\ 4\0\0¼àVba\ 4\0\0\v     qä\ 1\0\0\0\0\0\0Y\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php\97\ 2\0\0¼àVb\97\ 2\0\04~¾ ¤\ 1\0\0\0\0\0\0\\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php\89\ 1\0\0¼àVb\89\ 1\0\0\93µ+j¤\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php\1f\ f\0\0¼àVb\1f\ f\0\0ª%}\ f¤\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php,"\0\0¼àVb,"\0\0\17\ 1\89\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0¼àVbè\ 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¼àVbI\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¼àVb\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¼àVbl\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¼àVbl\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¼àVbu\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¼àVbw\0\0\0N-ò[¤\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0¼àVbÞ\ 2\0\0\r
58 ¤\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0¼àVbo\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¼àVb\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¼àVb\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¼àVbj\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¼àVbf\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¼àVbþ\ 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¼àVb \ 2\0\0f4÷³¤\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\93\r\0\0¼àVb\93\r\0\0&zß^¤\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php\ 1\ 1\0\0¼àVb\ 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¼àVbá\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¼àVb£\ 4\0\0Ç\92ô¦¤\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php \ 5\0\0¼àVb \ 5\0\0£Á\1f\16¤\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php,\ 2\0\0¼àVb,\ 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¼àVb®\0\0\0ÿ\8bÁå¤\ 1\0\0\0\0\0\0C\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php\ 4\v\0\0¼àVb\ 4\v\0\0æ\ 6\1a\ 1\0\0\0\0\0\0D\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php@\14\0\0¼àVb@\14\0\05\eÎ3¤\ 1\0\0\0\0\0\0H\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php\83\0\0\0¼àVb\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¼àVb\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phps\ 5\0\0¼àVbs\ 5\0\0ßÁ\91\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0¼àVb\1c\ 4\0\0\ 6Bhí¤\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.php{\15\0\0¼àVb{\15\0\0\9e \ 4\93¤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0¼àVb\1c\ 4\0\0\ 6Bhí¤\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0¼àVb\ 2\ 4\0\0wl\83ï¤\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.phpê\ 2\0\0¼àVbê\ 2\0\0M äˤ\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.php\8a\f\0\0¼àVb\8a\f\0\0Ò      \90
59 ¤\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0¼àVbß\0\0\00C,\87¤\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpä\ 1\0\0¼àVbä\ 1\0\0ïõ\82³¤\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php,\ 5\0\0¼àVb,\ 5\0\0\ 2\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.php\7f\ 6\0\0¼àVb\7f\ 6\0\0 YûÀ¤\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.phpw-\0\0¼àVbw-\0\0Î=ð­¤\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0¼àVb\1c\ 4\0\0*!^`¤\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php\95$\0\0¼àVb\95$\0\0ÛnÓ\a¤\ 1\0\0\0\0\0\0&\0\0\0vendor/composer/xdebug-handler/LICENSE)\ 4\0\0¼àVb)\ 4\0\0#Ô;^¤\ 1\0\0\0\0\0\00\0\0\0vendor/composer/xdebug-handler/src/PhpConfig.php´\ 2\0\0¼àVb´\ 2\0\0*D\92\0¤\ 1\0\0\0\0\0\0.\0\0\0vendor/composer/xdebug-handler/src/Process.phpk        \0\0¼àVbk \0\0\8eUÿߤ\ 1\0\0\0\0\0\0-\0\0\0vendor/composer/xdebug-handler/src/Status.php\ f
60 \0\0¼àVb\ f
61 \0\0$\9fv-¤\ 1\0\0\0\0\0\04\0\0\0vendor/composer/xdebug-handler/src/XdebugHandler.php\87%\0\0¼àVb\87%\0\0¾L3\ 4¤\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0¼àVb=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0¼àVb;\ 4\0\0ñ>3[¤\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0¼àVb`\0\0\0 \88X1¤\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0¼àVbû\0\0\0jðñ8¤\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0¼àVb|\0\0\0$\13£\88¤\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0¼àVb§\0\0\0T½úB¤\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÈ\ 2\0\0¼àVbÈ\ 2\0\0\9a\1fx\1d¤\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpk\ 4\0\0¼àVbk\ 4\0\0£}\89\92¤\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php\9f\0\0\0¼àVb\9f\0\0\0\81Xóª¤\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/Test/DummyTest.phpp\0\0\0¼àVbp\0\0\0\1a\15Î\ 5¤\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php \r\0\0¼àVb \r\0\0\1d$/Ò¤\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/Test/TestLogger.php<\b\0\0¼àVb<\b\0\0þ(åI¤\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0¼àVb\82\0\0\0\ 1\84¤\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0¼àVbd\0\0\0Z¡¦H¤\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php÷\ 4\0\0¼àVb÷\ 4\0\0Å*\9a\16¤\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0¼àVbd\0\0\0Z¡¦H¤\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.php\1f\ 1\0\0¼àVb\1f\ 1\0\0¥\0 ®¤\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpL\a\0\0¼àVbL\a\0\0å\9d1\93¤\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php§
62 \0\0¼àVb§
63 \0\0²´©ë¤\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php¦\18\0\0¼àVb¦\18\0\0MI\0\8c¤\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pemÁ,\ 3\0¼àVbÁ,\ 3\0½_~\8e¤\ 1\0\0\0\0\0\0\f\0\0\0bin/composer\ 5\a\0\0¼àVb\ 5\a\0\0\19\bÉ\80¤\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0¼àVb.\ 4\0\0 Õ\b\ 3¤\ 1\0\0\0\0\0\0<?php
64
65
66
67
68
69
70
71
72
73
74
75 namespace Composer\Autoload;
76
77 use Composer\Config;
78 use Composer\EventDispatcher\EventDispatcher;
79 use Composer\Installer\InstallationManager;
80 use Composer\IO\IOInterface;
81 use Composer\Package\AliasPackage;
82 use Composer\Package\PackageInterface;
83 use Composer\Repository\InstalledRepositoryInterface;
84 use Composer\Util\Filesystem;
85 use Composer\Script\ScriptEvents;
86 use Composer\Util\PackageSorter;
87
88
89
90
91
92 class AutoloadGenerator
93 {
94
95
96
97 private $eventDispatcher;
98
99
100
101
102 private $io;
103
104
105
106
107 private $devMode = false;
108
109
110
111
112 private $classMapAuthoritative = false;
113
114
115
116
117 private $apcu = false;
118
119
120
121
122 private $runScripts = false;
123
124 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
125 {
126 $this->eventDispatcher = $eventDispatcher;
127 $this->io = $io;
128 }
129
130 public function setDevMode($devMode = true)
131 {
132 $this->devMode = (bool) $devMode;
133 }
134
135
136
137
138
139
140
141 public function setClassMapAuthoritative($classMapAuthoritative)
142 {
143 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
144 }
145
146
147
148
149
150
151 public function setApcu($apcu)
152 {
153 $this->apcu = (bool) $apcu;
154 }
155
156
157
158
159
160
161 public function setRunScripts($runScripts = true)
162 {
163 $this->runScripts = (bool) $runScripts;
164 }
165
166 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '')
167 {
168 if ($this->classMapAuthoritative) {
169
170 $scanPsrPackages = true;
171 }
172 if ($this->runScripts) {
173 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
174 'optimize' => (bool) $scanPsrPackages,
175 ));
176 }
177
178 $filesystem = new Filesystem();
179 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
180
181
182
183 $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
184 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
185 $useGlobalIncludePath = (bool) $config->get('use-include-path');
186 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
187 $targetDir = $vendorPath.'/'.$targetDir;
188 $filesystem->ensureDirectoryExists($targetDir);
189
190 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
191 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
192 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
193
194 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
195 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
196
197 $namespacesFile = <<<EOF
198 <?php
199
200 // autoload_namespaces.php @generated by Composer
201
202 \$vendorDir = $vendorPathCode52;
203 \$baseDir = $appBaseDirCode;
204
205 return array(
206
207 EOF;
208
209 $psr4File = <<<EOF
210 <?php
211
212 // autoload_psr4.php @generated by Composer
213
214 \$vendorDir = $vendorPathCode52;
215 \$baseDir = $appBaseDirCode;
216
217 return array(
218
219 EOF;
220
221
222 $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
223 $autoloads = $this->parseAutoloads($packageMap, $mainPackage, $this->devMode === false);
224
225
226 foreach ($autoloads['psr-0'] as $namespace => $paths) {
227 $exportedPaths = array();
228 foreach ($paths as $path) {
229 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
230 }
231 $exportedPrefix = var_export($namespace, true);
232 $namespacesFile .= "    $exportedPrefix => ";
233 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
234 }
235 $namespacesFile .= ");\n";
236
237
238 foreach ($autoloads['psr-4'] as $namespace => $paths) {
239 $exportedPaths = array();
240 foreach ($paths as $path) {
241 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
242 }
243 $exportedPrefix = var_export($namespace, true);
244 $psr4File .= "    $exportedPrefix => ";
245 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
246 }
247 $psr4File .= ");\n";
248
249 $classmapFile = <<<EOF
250 <?php
251
252 // autoload_classmap.php @generated by Composer
253
254 \$vendorDir = $vendorPathCode52;
255 \$baseDir = $appBaseDirCode;
256
257 return array(
258
259 EOF;
260
261
262 $targetDirLoader = null;
263 $mainAutoload = $mainPackage->getAutoload();
264 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
265 $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
266 $prefixes = implode(', ', array_map(function ($prefix) {
267 return var_export($prefix, true);
268 }, array_keys($mainAutoload['psr-0'])));
269 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
270
271 $targetDirLoader = <<<EOF
272
273     public static function autoload(\$class)
274     {
275         \$dir = $baseDirFromTargetDirCode . '/';
276         \$prefixes = array($prefixes);
277         foreach (\$prefixes as \$prefix) {
278             if (0 !== strpos(\$class, \$prefix)) {
279                 continue;
280             }
281             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
282             if (!\$path = stream_resolve_include_path(\$path)) {
283                 return false;
284             }
285             require \$path;
286
287             return true;
288         }
289     }
290
291 EOF;
292 }
293
294 $excluded = null;
295 if (!empty($autoloads['exclude-from-classmap'])) {
296 $excluded = $autoloads['exclude-from-classmap'];
297 }
298
299 $classMap = array();
300 $ambiguousClasses = array();
301 $scannedFiles = array();
302 foreach ($autoloads['classmap'] as $dir) {
303 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $excluded, null, null, $classMap, $ambiguousClasses, $scannedFiles);
304 }
305
306 if ($scanPsrPackages) {
307 $namespacesToScan = array();
308
309
310 foreach (array('psr-4', 'psr-0') as $psrType) {
311 foreach ($autoloads[$psrType] as $namespace => $paths) {
312 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
313 }
314 }
315
316 krsort($namespacesToScan);
317
318 foreach ($namespacesToScan as $namespace => $groups) {
319 foreach ($groups as $group) {
320 foreach ($group['paths'] as $dir) {
321 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
322 if (!is_dir($dir)) {
323 continue;
324 }
325
326 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $excluded, $namespace, $group['type'], $classMap, $ambiguousClasses, $scannedFiles);
327 }
328 }
329 }
330 }
331
332 foreach ($ambiguousClasses as $className => $ambigiousPaths) {
333 $cleanPath = str_replace(array('$vendorDir . \'', '$baseDir . \'', "',\n"), array($vendorPath, $basePath, ''), $classMap[$className]);
334
335 $this->io->writeError(
336 '<warning>Warning: Ambiguous class resolution, "'.$className.'"'.
337 ' was found '. (count($ambigiousPaths) + 1) .'x: in "'.$cleanPath.'" and "'. implode('", "', $ambigiousPaths) .'", the first will be used.</warning>'
338 );
339 }
340
341 ksort($classMap);
342 foreach ($classMap as $class => $code) {
343 $classmapFile .= '    '.var_export($class, true).' => '.$code;
344 }
345 $classmapFile .= ");\n";
346
347 if (!$suffix) {
348 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
349 $content = file_get_contents($vendorPath.'/autoload.php');
350 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
351 $suffix = $match[1];
352 }
353 }
354
355 if (!$suffix) {
356 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
357 }
358 }
359
360 $this->filePutContentsIfModified($targetDir.'/autoload_namespaces.php', $namespacesFile);
361 $this->filePutContentsIfModified($targetDir.'/autoload_psr4.php', $psr4File);
362 $this->filePutContentsIfModified($targetDir.'/autoload_classmap.php', $classmapFile);
363 $includePathFilePath = $targetDir.'/include_paths.php';
364 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
365 $this->filePutContentsIfModified($includePathFilePath, $includePathFileContents);
366 } elseif (file_exists($includePathFilePath)) {
367 unlink($includePathFilePath);
368 }
369 $includeFilesFilePath = $targetDir.'/autoload_files.php';
370 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
371 $this->filePutContentsIfModified($includeFilesFilePath, $includeFilesFileContents);
372 } elseif (file_exists($includeFilesFilePath)) {
373 unlink($includeFilesFilePath);
374 }
375 $this->filePutContentsIfModified($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
376 $this->filePutContentsIfModified($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
377 $this->filePutContentsIfModified($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
378
379 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
380 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
381
382 if ($this->runScripts) {
383 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
384 'optimize' => (bool) $scanPsrPackages,
385 ));
386 }
387
388 return count($classMap);
389 }
390
391 private function filePutContentsIfModified($path, $content)
392 {
393 $currentContent = @file_get_contents($path);
394 if (!$currentContent || ($currentContent != $content)) {
395 return file_put_contents($path, $content);
396 }
397
398 return 0;
399 }
400
401 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $excluded, $namespaceFilter, $autoloadType, array $classMap, array &$ambiguousClasses, array &$scannedFiles)
402 {
403 foreach ($this->generateClassMap($dir, $excluded, $namespaceFilter, $autoloadType, true, $scannedFiles) as $class => $path) {
404 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
405 if (!isset($classMap[$class])) {
406 $classMap[$class] = $pathCode;
407 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
408 $ambiguousClasses[$class][] = $path;
409 }
410 }
411
412 return $classMap;
413 }
414
415
416
417
418 private function generateClassMap($dir, $excluded, $namespaceFilter, $autoloadType, $showAmbiguousWarning, array &$scannedFiles)
419 {
420 if ($excluded) {
421
422
423
424 if (file_exists($dir)) {
425
426 $dirMatch = preg_quote(strtr(realpath($dir), '\\', '/'));
427 foreach ($excluded as $index => $pattern) {
428
429 $pattern = preg_replace('{^(([^.+*?\[^\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\[^\]$(){}=!<>|:#-])*).*}', '$1', $pattern);
430
431 if (0 !== strpos($pattern, $dirMatch) && 0 !== strpos($dirMatch, $pattern)) {
432 unset($excluded[$index]);
433 }
434 }
435 }
436
437 $excluded = $excluded ? '{(' . implode('|', $excluded) . ')}' : null;
438 }
439
440 return ClassMapGenerator::createMap($dir, $excluded, $showAmbiguousWarning ? $this->io : null, $namespaceFilter, $autoloadType, $scannedFiles);
441 }
442
443 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
444 {
445
446 $packageMap = array(array($mainPackage, ''));
447
448 foreach ($packages as $package) {
449 if ($package instanceof AliasPackage) {
450 continue;
451 }
452 $this->validatePackage($package);
453
454 $packageMap[] = array(
455 $package,
456 $installationManager->getInstallPath($package),
457 );
458 }
459
460 return $packageMap;
461 }
462
463
464
465
466
467
468 protected function validatePackage(PackageInterface $package)
469 {
470 $autoload = $package->getAutoload();
471 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
472 $name = $package->getName();
473 $package->getTargetDir();
474 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
475 }
476 if (!empty($autoload['psr-4'])) {
477 foreach ($autoload['psr-4'] as $namespace => $dirs) {
478 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
479 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
480 }
481 }
482 }
483 }
484
485
486
487
488
489
490
491
492
493 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage, $filterOutRequireDevPackages = false)
494 {
495 $mainPackageMap = array_shift($packageMap);
496 if ($filterOutRequireDevPackages) {
497 $packageMap = $this->filterPackageMap($packageMap, $mainPackage);
498 }
499 $sortedPackageMap = $this->sortPackageMap($packageMap);
500 $sortedPackageMap[] = $mainPackageMap;
501 array_unshift($packageMap, $mainPackageMap);
502
503 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
504 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
505 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
506 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
507 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
508
509 krsort($psr0);
510 krsort($psr4);
511
512 return array(
513 'psr-0' => $psr0,
514 'psr-4' => $psr4,
515 'classmap' => $classmap,
516 'files' => $files,
517 'exclude-from-classmap' => $exclude,
518 );
519 }
520
521
522
523
524
525
526
527 public function createLoader(array $autoloads)
528 {
529 $loader = new ClassLoader();
530
531 if (isset($autoloads['psr-0'])) {
532 foreach ($autoloads['psr-0'] as $namespace => $path) {
533 $loader->add($namespace, $path);
534 }
535 }
536
537 if (isset($autoloads['psr-4'])) {
538 foreach ($autoloads['psr-4'] as $namespace => $path) {
539 $loader->addPsr4($namespace, $path);
540 }
541 }
542
543 if (isset($autoloads['classmap'])) {
544 $excluded = null;
545 if (!empty($autoloads['exclude-from-classmap'])) {
546 $excluded = $autoloads['exclude-from-classmap'];
547 }
548
549 $scannedFiles = array();
550 foreach ($autoloads['classmap'] as $dir) {
551 try {
552 $loader->addClassMap($this->generateClassMap($dir, $excluded, null, null, false, $scannedFiles));
553 } catch (\RuntimeException $e) {
554 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
555 }
556 }
557 }
558
559 return $loader;
560 }
561
562 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
563 {
564 $includePaths = array();
565
566 foreach ($packageMap as $item) {
567 list($package, $installPath) = $item;
568
569 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
570 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
571 }
572
573 foreach ($package->getIncludePaths() as $includePath) {
574 $includePath = trim($includePath, '/');
575 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
576 }
577 }
578
579 if (!$includePaths) {
580 return;
581 }
582
583 $includePathsCode = '';
584 foreach ($includePaths as $path) {
585 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
586 }
587
588 return <<<EOF
589 <?php
590
591 // include_paths.php @generated by Composer
592
593 \$vendorDir = $vendorPathCode;
594 \$baseDir = $appBaseDirCode;
595
596 return array(
597 $includePathsCode);
598
599 EOF;
600 }
601
602 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
603 {
604 $filesCode = '';
605 foreach ($files as $fileIdentifier => $functionFile) {
606 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
607 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
608 }
609
610 if (!$filesCode) {
611 return false;
612 }
613
614 return <<<EOF
615 <?php
616
617 // autoload_files.php @generated by Composer
618
619 \$vendorDir = $vendorPathCode;
620 \$baseDir = $appBaseDirCode;
621
622 return array(
623 $filesCode);
624
625 EOF;
626 }
627
628 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
629 {
630 if (!$filesystem->isAbsolutePath($path)) {
631 $path = $basePath . '/' . $path;
632 }
633 $path = $filesystem->normalizePath($path);
634
635 $baseDir = '';
636 if (strpos($path.'/', $vendorPath.'/') === 0) {
637 $path = substr($path, strlen($vendorPath));
638 $baseDir = '$vendorDir';
639
640 if ($path !== false) {
641 $baseDir .= " . ";
642 }
643 } else {
644 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
645 if (!$filesystem->isAbsolutePath($path)) {
646 $baseDir = '$baseDir . ';
647 $path = '/' . $path;
648 }
649 }
650
651 if (strpos($path, '.phar') !== false) {
652 $baseDir = "'phar://' . " . $baseDir;
653 }
654
655 return $baseDir . (($path !== false) ? var_export($path, true) : "");
656 }
657
658 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
659 {
660 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
661 if ("'" === $lastChar || '"' === $lastChar) {
662 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
663 } else {
664 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
665 }
666
667 return <<<AUTOLOAD
668 <?php
669
670 // autoload.php @generated by Composer
671
672 require_once $vendorPathToTargetDirCode;
673
674 return ComposerAutoloaderInit$suffix::getLoader();
675
676 AUTOLOAD;
677 }
678
679 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
680 {
681 $file = <<<HEADER
682 <?php
683
684 // autoload_real.php @generated by Composer
685
686 class ComposerAutoloaderInit$suffix
687 {
688     private static \$loader;
689
690     public static function loadClassLoader(\$class)
691     {
692         if ('Composer\\Autoload\\ClassLoader' === \$class) {
693             require __DIR__ . '/ClassLoader.php';
694         }
695     }
696
697     /**
698      * @return \Composer\Autoload\ClassLoader
699      */
700     public static function getLoader()
701     {
702         if (null !== self::\$loader) {
703             return self::\$loader;
704         }
705
706         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
707         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
708         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
709
710
711 HEADER;
712
713 if ($useIncludePath) {
714 $file .= <<<'INCLUDE_PATH'
715         $includePaths = require __DIR__ . '/include_paths.php';
716         $includePaths[] = get_include_path();
717         set_include_path(implode(PATH_SEPARATOR, $includePaths));
718
719
720 INCLUDE_PATH;
721 }
722
723 $file .= <<<STATIC_INIT
724         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
725         if (\$useStaticLoader) {
726             require_once __DIR__ . '/autoload_static.php';
727
728             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
729         } else {
730
731 STATIC_INIT;
732
733 if (!$this->classMapAuthoritative) {
734 $file .= <<<'PSR04'
735             $map = require __DIR__ . '/autoload_namespaces.php';
736             foreach ($map as $namespace => $path) {
737                 $loader->set($namespace, $path);
738             }
739
740             $map = require __DIR__ . '/autoload_psr4.php';
741             foreach ($map as $namespace => $path) {
742                 $loader->setPsr4($namespace, $path);
743             }
744
745
746 PSR04;
747 }
748
749 if ($useClassMap) {
750 $file .= <<<'CLASSMAP'
751             $classMap = require __DIR__ . '/autoload_classmap.php';
752             if ($classMap) {
753                 $loader->addClassMap($classMap);
754             }
755
756 CLASSMAP;
757 }
758
759 $file .= "        }\n\n";
760
761 if ($this->classMapAuthoritative) {
762 $file .= <<<'CLASSMAPAUTHORITATIVE'
763         $loader->setClassMapAuthoritative(true);
764
765 CLASSMAPAUTHORITATIVE;
766 }
767
768 if ($this->apcu) {
769 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
770 $file .= <<<APCU
771         \$loader->setApcuPrefix('$apcuPrefix');
772
773 APCU;
774 }
775
776 if ($useGlobalIncludePath) {
777 $file .= <<<'INCLUDEPATH'
778         $loader->setUseIncludePath(true);
779
780 INCLUDEPATH;
781 }
782
783 if ($targetDirLoader) {
784 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
785         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
786
787
788 REGISTER_TARGET_DIR_AUTOLOAD;
789 }
790
791 $file .= <<<REGISTER_LOADER
792         \$loader->register($prependAutoloader);
793
794
795 REGISTER_LOADER;
796
797 if ($useIncludeFiles) {
798 $file .= <<<INCLUDE_FILES
799         if (\$useStaticLoader) {
800             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
801         } else {
802             \$includeFiles = require __DIR__ . '/autoload_files.php';
803         }
804         foreach (\$includeFiles as \$fileIdentifier => \$file) {
805             composerRequire$suffix(\$fileIdentifier, \$file);
806         }
807
808
809 INCLUDE_FILES;
810 }
811
812 $file .= <<<METHOD_FOOTER
813         return \$loader;
814     }
815
816 METHOD_FOOTER;
817
818 $file .= $targetDirLoader;
819
820 if ($useIncludeFiles) {
821 return $file . <<<FOOTER
822 }
823
824 function composerRequire$suffix(\$fileIdentifier, \$file)
825 {
826     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
827         require \$file;
828
829         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
830     }
831 }
832
833 FOOTER;
834 }
835
836 return $file . <<<FOOTER
837 }
838
839 FOOTER;
840 }
841
842 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
843 {
844 $staticPhpVersion = 50600;
845
846 $file = <<<HEADER
847 <?php
848
849 // autoload_static.php @generated by Composer
850
851 namespace Composer\Autoload;
852
853 class ComposerStaticInit$suffix
854 {
855
856 HEADER;
857
858 $loader = new ClassLoader();
859
860 $map = require $targetDir . '/autoload_namespaces.php';
861 foreach ($map as $namespace => $path) {
862 $loader->set($namespace, $path);
863 }
864
865 $map = require $targetDir . '/autoload_psr4.php';
866 foreach ($map as $namespace => $path) {
867 $loader->setPsr4($namespace, $path);
868 }
869
870 $classMap = require $targetDir . '/autoload_classmap.php';
871 if ($classMap) {
872 $loader->addClassMap($classMap);
873 }
874
875 $filesystem = new Filesystem();
876
877 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
878 $vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
879 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
880 $appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
881
882 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
883 $absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\\/') . '/', true), 0, -1);
884 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
885 $absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\\/') . '/', true), 0, -1);
886
887 $initializer = '';
888 $prefix = "\0Composer\Autoload\ClassLoader\0";
889 $prefixLen = strlen($prefix);
890 if (file_exists($targetDir . '/autoload_files.php')) {
891 $maps = array('files' => require $targetDir . '/autoload_files.php');
892 } else {
893 $maps = array();
894 }
895
896 foreach ((array) $loader as $prop => $value) {
897 if ($value && 0 === strpos($prop, $prefix)) {
898 $maps[substr($prop, $prefixLen)] = $value;
899 }
900 }
901
902 foreach ($maps as $prop => $value) {
903 if (count($value) > 32767) {
904
905
906 $staticPhpVersion = 70000;
907 }
908 $value = strtr(
909 var_export($value, true),
910 array(
911 $absoluteVendorPathCode => $vendorPathCode,
912 $absoluteVendorPharPathCode => $vendorPharPathCode,
913 $absoluteAppBaseDirCode => $appBaseDirCode,
914 $absoluteAppBaseDirPharCode => $appBaseDirPharCode,
915 )
916 );
917 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
918
919 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
920 if ('files' !== $prop) {
921 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
922 }
923 }
924
925 return $file . <<<INITIALIZER
926     public static function getInitializer(ClassLoader \$loader)
927     {
928         return \Closure::bind(function () use (\$loader) {
929 $initializer
930         }, null, ClassLoader::class);
931     }
932 }
933
934 INITIALIZER;
935 }
936
937 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
938 {
939 $autoloads = array();
940
941 foreach ($packageMap as $item) {
942 list($package, $installPath) = $item;
943
944 $autoload = $package->getAutoload();
945 if ($this->devMode && $package === $mainPackage) {
946 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
947 }
948
949
950 if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
951 continue;
952 }
953 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
954 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
955 }
956
957 foreach ($autoload[$type] as $namespace => $paths) {
958 foreach ((array) $paths as $path) {
959 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
960
961 if ($package === $mainPackage) {
962 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
963 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
964 } else {
965
966 $path = $package->getTargetDir() . '/' . $path;
967 }
968 }
969
970 if ($type === 'exclude-from-classmap') {
971
972 $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
973
974
975 $path = str_replace('\\*\\*', '.+?', $path);
976 $path = str_replace('\\*', '[^/]+?', $path);
977
978
979 $updir = null;
980 $path = preg_replace_callback(
981 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
982 function ($matches) use (&$updir) {
983 if (isset($matches[1])) {
984
985 $updir = str_replace('\\.', '.', $matches[1]);
986 }
987
988 return '';
989 },
990 $path
991 );
992 if (empty($installPath)) {
993 $installPath = strtr(getcwd(), '\\', '/');
994 }
995
996 $resolvedPath = realpath($installPath . '/' . $updir);
997 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path . '($|/)';
998 continue;
999 }
1000
1001 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
1002
1003 if ($type === 'files') {
1004 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
1005 continue;
1006 } elseif ($type === 'classmap') {
1007 $autoloads[] = $relativePath;
1008 continue;
1009 }
1010
1011 $autoloads[$namespace][] = $relativePath;
1012 }
1013 }
1014 }
1015
1016 return $autoloads;
1017 }
1018
1019 protected function getFileIdentifier(PackageInterface $package, $path)
1020 {
1021 return md5($package->getName() . ':' . $path);
1022 }
1023
1024
1025
1026
1027
1028
1029
1030
1031 protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage)
1032 {
1033 $packages = array();
1034 $include = array();
1035 $replacedBy = array();
1036
1037 foreach ($packageMap as $item) {
1038 $package = $item[0];
1039 $name = $package->getName();
1040 $packages[$name] = $package;
1041 foreach ($package->getReplaces() as $replace) {
1042 $replacedBy[$replace->getTarget()] = $name;
1043 }
1044 }
1045
1046 $add = function (PackageInterface $package) use (&$add, $packages, &$include, $replacedBy) {
1047 foreach ($package->getRequires() as $link) {
1048 $target = $link->getTarget();
1049 if (isset($replacedBy[$target])) {
1050 $target = $replacedBy[$target];
1051 }
1052 if (!isset($include[$target])) {
1053 $include[$target] = true;
1054 if (isset($packages[$target])) {
1055 $add($packages[$target]);
1056 }
1057 }
1058 }
1059 };
1060 $add($mainPackage);
1061
1062 return array_filter(
1063 $packageMap,
1064 function ($item) use ($include) {
1065 $package = $item[0];
1066 foreach ($package->getNames() as $name) {
1067 if (isset($include[$name])) {
1068 return true;
1069 }
1070 }
1071
1072 return false;
1073 }
1074 );
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085 protected function sortPackageMap(array $packageMap)
1086 {
1087 $packages = array();
1088 $paths = array();
1089
1090 foreach ($packageMap as $item) {
1091 list($package, $path) = $item;
1092 $name = $package->getName();
1093 $packages[$name] = $package;
1094 $paths[$name] = $path;
1095 }
1096
1097 $sortedPackages = PackageSorter::sortPackages($packages);
1098
1099 $sortedPackageMap = array();
1100
1101 foreach ($sortedPackages as $package) {
1102 $name = $package->getName();
1103 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1104 }
1105
1106 return $sortedPackageMap;
1107 }
1108
1109
1110
1111
1112
1113
1114
1115 protected function safeCopy($source, $target)
1116 {
1117 if (!file_exists($target) || !file_exists($source) || !$this->filesAreEqual($source, $target)) {
1118 $source = fopen($source, 'r');
1119 $target = fopen($target, 'w+');
1120
1121 stream_copy_to_stream($source, $target);
1122 fclose($source);
1123 fclose($target);
1124 }
1125 }
1126
1127
1128
1129
1130
1131 private function filesAreEqual($a, $b)
1132 {
1133
1134 if (filesize($a) !== filesize($b)) {
1135 return false;
1136 }
1137
1138
1139 $ah = fopen($a, 'rb');
1140 $bh = fopen($b, 'rb');
1141
1142 $result = true;
1143 while (!feof($ah)) {
1144 if (fread($ah, 8192) != fread($bh, 8192)) {
1145 $result = false;
1146 break;
1147 }
1148 }
1149
1150 fclose($ah);
1151 fclose($bh);
1152
1153 return $result;
1154 }
1155 }
1156 <?php
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174 namespace Composer\Autoload;
1175
1176 use Symfony\Component\Finder\Finder;
1177 use Composer\IO\IOInterface;
1178 use Composer\Util\Filesystem;
1179
1180
1181
1182
1183
1184
1185
1186 class ClassMapGenerator
1187 {
1188
1189
1190
1191
1192
1193
1194 public static function dump($dirs, $file)
1195 {
1196 $maps = array();
1197
1198 foreach ($dirs as $dir) {
1199 $maps = array_merge($maps, static::createMap($dir));
1200 }
1201
1202 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217 public static function createMap($path, $excluded = null, IOInterface $io = null, $namespace = null, $autoloadType = null, &$scannedFiles = array())
1218 {
1219 if (is_string($path)) {
1220 $basePath = $path;
1221 if (is_file($path)) {
1222 $path = array(new \SplFileInfo($path));
1223 } elseif (is_dir($path)) {
1224 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1225 } else {
1226 throw new \RuntimeException(
1227 'Could not scan for classes inside "'.$path.
1228 '" which does not appear to be a file nor a folder'
1229 );
1230 }
1231 } elseif (null !== $autoloadType) {
1232 throw new \RuntimeException('Path must be a string when specifying an autoload type');
1233 }
1234
1235 $map = array();
1236 $filesystem = new Filesystem();
1237 $cwd = realpath(getcwd());
1238
1239 foreach ($path as $file) {
1240 $filePath = $file->getPathname();
1241 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1242 continue;
1243 }
1244
1245 if (!$filesystem->isAbsolutePath($filePath)) {
1246 $filePath = $cwd . '/' . $filePath;
1247 $filePath = $filesystem->normalizePath($filePath);
1248 } else {
1249 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1250 }
1251
1252 $realPath = realpath($filePath);
1253
1254
1255
1256 if (isset($scannedFiles[$realPath])) {
1257 continue;
1258 }
1259
1260
1261 if ($excluded && preg_match($excluded, strtr($realPath, '\\', '/'))) {
1262 continue;
1263 }
1264
1265 if ($excluded && preg_match($excluded, strtr($filePath, '\\', '/'))) {
1266 continue;
1267 }
1268
1269 $classes = self::findClasses($filePath);
1270 if (null !== $autoloadType) {
1271 list($classes, $validClasses) = self::filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath, $io);
1272
1273
1274 if ($validClasses) {
1275 $scannedFiles[$realPath] = true;
1276 }
1277 } else {
1278
1279 $scannedFiles[$realPath] = true;
1280 }
1281
1282 foreach ($classes as $class) {
1283
1284
1285 if ( null !== $namespace && '' !== $namespace && 0 !== strpos($class, $namespace)) {
1286 continue;
1287 }
1288
1289 if (!isset($map[$class])) {
1290 $map[$class] = $filePath;
1291 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1292 $io->writeError(
1293 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1294 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1295 );
1296 }
1297 }
1298 }
1299
1300 return $map;
1301 }
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314 private static function filterByNamespace($classes, $filePath, $baseNamespace, $namespaceType, $basePath, $io)
1315 {
1316 $validClasses = array();
1317 $rejectedClasses = array();
1318
1319 $realSubPath = substr($filePath, strlen($basePath) + 1);
1320 $realSubPath = substr($realSubPath, 0, strrpos($realSubPath, '.'));
1321
1322 foreach ($classes as $class) {
1323
1324 if ('' !== $baseNamespace && 0 !== strpos($class, $baseNamespace)) {
1325 continue;
1326 }
1327
1328 if ('psr-0' === $namespaceType) {
1329 $namespaceLength = strrpos($class, '\\');
1330 if (false !== $namespaceLength) {
1331 $namespace = substr($class, 0, $namespaceLength + 1);
1332 $className = substr($class, $namespaceLength + 1);
1333 $subPath = str_replace('\\', DIRECTORY_SEPARATOR, $namespace)
1334 . str_replace('_', DIRECTORY_SEPARATOR, $className);
1335 }
1336 else {
1337 $subPath = str_replace('_', DIRECTORY_SEPARATOR, $class);
1338 }
1339 } elseif ('psr-4' === $namespaceType) {
1340 $subNamespace = ('' !== $baseNamespace) ? substr($class, strlen($baseNamespace)) : $class;
1341 $subPath = str_replace('\\', DIRECTORY_SEPARATOR, $subNamespace);
1342 } else {
1343 throw new \RuntimeException("namespaceType must be psr-0 or psr-4, $namespaceType given");
1344 }
1345 if ($subPath === $realSubPath) {
1346 $validClasses[] = $class;
1347 } else {
1348 $rejectedClasses[] = $class;
1349 }
1350 }
1351
1352 if (empty($validClasses)) {
1353 foreach ($rejectedClasses as $class) {
1354 trigger_error(
1355 "Class $class located in ".preg_replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. It will not autoload anymore in Composer v2.0.",
1356 E_USER_DEPRECATED
1357 );
1358 }
1359
1360
1361
1362 }
1363
1364
1365
1366 return array($classes, $validClasses);
1367 }
1368
1369
1370
1371
1372
1373
1374
1375
1376 private static function findClasses($path)
1377 {
1378 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1379 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1380 $extraTypes .= '|enum';
1381 }
1382
1383
1384
1385 $contents = @php_strip_whitespace($path);
1386 if (!$contents) {
1387 if (!file_exists($path)) {
1388 $message = 'File at "%s" does not exist, check your classmap definitions';
1389 } elseif (!is_readable($path)) {
1390 $message = 'File at "%s" is not readable, check its permissions';
1391 } elseif ('' === trim(file_get_contents($path))) {
1392
1393 return array();
1394 } else {
1395 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1396 }
1397 $error = error_get_last();
1398 if (isset($error['message'])) {
1399 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1400 }
1401 throw new \RuntimeException(sprintf($message, $path));
1402 }
1403
1404
1405 if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1406 return array();
1407 }
1408
1409
1410 $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
1411
1412 $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1413
1414 if (substr($contents, 0, 2) !== '<?') {
1415 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1416 if ($replacements === 0) {
1417 return array();
1418 }
1419 }
1420
1421 $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
1422
1423 $pos = strrpos($contents, '?>');
1424 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1425 $contents = substr($contents, 0, $pos);
1426 }
1427
1428 if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
1429 $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
1430 }
1431
1432 preg_match_all('{
1433             (?:
1434                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1435                | \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*+ [\{;]
1436             )
1437         }ix', $contents, $matches);
1438
1439 $classes = array();
1440 $namespace = '';
1441
1442 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1443 if (!empty($matches['ns'][$i])) {
1444 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1445 } else {
1446 $name = $matches['name'][$i];
1447
1448 if ($name === 'extends' || $name === 'implements') {
1449 continue;
1450 }
1451 if ($name[0] === ':') {
1452
1453 $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1454 } elseif ($matches['type'][$i] === 'enum') {
1455
1456
1457
1458
1459 $name = rtrim($name, ':');
1460 }
1461 $classes[] = ltrim($namespace . $name, '\\');
1462 }
1463 }
1464
1465 return $classes;
1466 }
1467 }
1468 <?php
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480 namespace Composer;
1481
1482 use Composer\IO\IOInterface;
1483 use Composer\Util\Filesystem;
1484 use Composer\Util\Silencer;
1485 use Symfony\Component\Finder\Finder;
1486
1487
1488
1489
1490
1491
1492 class Cache
1493 {
1494 private static $cacheCollected = false;
1495 private $io;
1496 private $root;
1497 private $enabled = true;
1498 private $allowList;
1499 private $filesystem;
1500
1501
1502
1503
1504
1505
1506
1507 public function __construct(IOInterface $io, $cacheDir, $allowList = 'a-z0-9.', Filesystem $filesystem = null)
1508 {
1509 $this->io = $io;
1510 $this->root = rtrim($cacheDir, '/\\') . '/';
1511 $this->allowList = $allowList;
1512 $this->filesystem = $filesystem ?: new Filesystem();
1513
1514 if (!self::isUsable($cacheDir)) {
1515 $this->enabled = false;
1516
1517 return;
1518 }
1519
1520 if (
1521 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1522 || !is_writable($this->root)
1523 ) {
1524 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1525 $this->enabled = false;
1526 }
1527 }
1528
1529 public static function isUsable($path)
1530 {
1531 return !preg_match('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path);
1532 }
1533
1534 public function isEnabled()
1535 {
1536 return $this->enabled;
1537 }
1538
1539 public function getRoot()
1540 {
1541 return $this->root;
1542 }
1543
1544 public function read($file)
1545 {
1546 if ($this->enabled) {
1547 $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
1548 if (file_exists($this->root . $file)) {
1549 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1550
1551 return file_get_contents($this->root . $file);
1552 }
1553 }
1554
1555 return false;
1556 }
1557
1558 public function write($file, $contents)
1559 {
1560 if ($this->enabled) {
1561 $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
1562
1563 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1564
1565 try {
1566 return file_put_contents($this->root . $file, $contents);
1567 } catch (\ErrorException $e) {
1568 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1569 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1570
1571 unlink($this->root . $file);
1572
1573 $message = sprintf(
1574 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1575 $this->root . $file,
1576 $m[1],
1577 $m[2],
1578 @disk_free_space($this->root . dirname($file))
1579 );
1580
1581 $this->io->writeError($message);
1582
1583 return false;
1584 }
1585
1586 throw $e;
1587 }
1588 }
1589
1590 return false;
1591 }
1592
1593
1594
1595
1596 public function copyFrom($file, $source)
1597 {
1598 if ($this->enabled) {
1599 $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
1600 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1601
1602 if (!file_exists($source)) {
1603 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1604 } elseif ($this->io->isDebug()) {
1605 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1606 }
1607
1608 return copy($source, $this->root . $file);
1609 }
1610
1611 return false;
1612 }
1613
1614
1615
1616
1617 public function copyTo($file, $target)
1618 {
1619 if ($this->enabled) {
1620 $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
1621 if (file_exists($this->root . $file)) {
1622 try {
1623 touch($this->root . $file, filemtime($this->root . $file), time());
1624 } catch (\ErrorException $e) {
1625
1626
1627 Silencer::call('touch', $this->root . $file);
1628 }
1629
1630 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1631
1632 return copy($this->root . $file, $target);
1633 }
1634 }
1635
1636 return false;
1637 }
1638
1639 public function gcIsNecessary()
1640 {
1641 return (!self::$cacheCollected && !mt_rand(0, 50));
1642 }
1643
1644 public function remove($file)
1645 {
1646 if ($this->enabled) {
1647 $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
1648 if (file_exists($this->root . $file)) {
1649 return $this->filesystem->unlink($this->root . $file);
1650 }
1651 }
1652
1653 return false;
1654 }
1655
1656 public function clear()
1657 {
1658 if ($this->enabled) {
1659 $this->filesystem->emptyDirectory($this->root);
1660 return true;
1661 }
1662
1663 return false;
1664 }
1665
1666 public function gc($ttl, $maxSize)
1667 {
1668 if ($this->enabled) {
1669 $expire = new \DateTime();
1670 $expire->modify('-'.$ttl.' seconds');
1671
1672 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1673 foreach ($finder as $file) {
1674 $this->filesystem->unlink($file->getPathname());
1675 }
1676
1677 $totalSize = $this->filesystem->size($this->root);
1678 if ($totalSize > $maxSize) {
1679 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1680 while ($totalSize > $maxSize && $iterator->valid()) {
1681 $filepath = $iterator->current()->getPathname();
1682 $totalSize -= $this->filesystem->size($filepath);
1683 $this->filesystem->unlink($filepath);
1684 $iterator->next();
1685 }
1686 }
1687
1688 self::$cacheCollected = true;
1689
1690 return true;
1691 }
1692
1693 return false;
1694 }
1695
1696 public function sha1($file)
1697 {
1698 if ($this->enabled) {
1699 $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
1700 if (file_exists($this->root . $file)) {
1701 return sha1_file($this->root . $file);
1702 }
1703 }
1704
1705 return false;
1706 }
1707
1708 public function sha256($file)
1709 {
1710 if ($this->enabled) {
1711 $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
1712 if (file_exists($this->root . $file)) {
1713 return hash_file('sha256', $this->root . $file);
1714 }
1715 }
1716
1717 return false;
1718 }
1719
1720 protected function getFinder()
1721 {
1722 return Finder::create()->in($this->root)->files();
1723 }
1724 }
1725 <?php
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737 namespace Composer\Command;
1738
1739 use Symfony\Component\Console\Input\InputInterface;
1740 use Symfony\Component\Console\Output\OutputInterface;
1741
1742
1743
1744
1745 class AboutCommand extends BaseCommand
1746 {
1747 protected function configure()
1748 {
1749 $this
1750 ->setName('about')
1751 ->setDescription('Shows the short information about Composer.')
1752 ->setHelp(
1753 <<<EOT
1754 <info>php composer.phar about</info>
1755 EOT
1756 )
1757 ;
1758 }
1759
1760 protected function execute(InputInterface $input, OutputInterface $output)
1761 {
1762 $this->getIO()->write(
1763 <<<EOT
1764 <info>Composer - Dependency Manager for PHP</info>
1765 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1766 See https://getcomposer.org/ for more information.</comment>
1767 EOT
1768 );
1769
1770 return 0;
1771 }
1772 }
1773 <?php
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785 namespace Composer\Command;
1786
1787 use Composer\Factory;
1788 use Composer\IO\IOInterface;
1789 use Composer\Config;
1790 use Composer\Composer;
1791 use Composer\Repository\CompositeRepository;
1792 use Composer\Repository\RepositoryFactory;
1793 use Composer\Script\ScriptEvents;
1794 use Composer\Plugin\CommandEvent;
1795 use Composer\Plugin\PluginEvents;
1796 use Composer\Util\Filesystem;
1797 use Symfony\Component\Console\Input\InputArgument;
1798 use Symfony\Component\Console\Input\InputInterface;
1799 use Symfony\Component\Console\Input\InputOption;
1800 use Symfony\Component\Console\Output\OutputInterface;
1801
1802
1803
1804
1805
1806
1807 class ArchiveCommand extends BaseCommand
1808 {
1809 protected function configure()
1810 {
1811 $this
1812 ->setName('archive')
1813 ->setDescription('Creates an archive of this composer package.')
1814 ->setDefinition(array(
1815 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1816 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1817 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1818 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1819 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1820 .' Note that the format will be appended.'),
1821 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1822 ))
1823 ->setHelp(
1824 <<<EOT
1825 The <info>archive</info> command creates an archive of the specified format
1826 containing the files and directories of the Composer project or the specified
1827 package in the specified version and writes it to the specified directory.
1828
1829 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1830
1831 Read more at https://getcomposer.org/doc/03-cli.md#archive
1832 EOT
1833 )
1834 ;
1835 }
1836
1837 protected function execute(InputInterface $input, OutputInterface $output)
1838 {
1839 $composer = $this->getComposer(false);
1840 $config = null;
1841
1842 if ($composer) {
1843 $config = $composer->getConfig();
1844 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1845 $eventDispatcher = $composer->getEventDispatcher();
1846 $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent);
1847 $eventDispatcher->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1848 }
1849
1850 if (!$config) {
1851 $config = Factory::createConfig();
1852 }
1853
1854 if (null === $input->getOption('format')) {
1855 $input->setOption('format', $config->get('archive-format'));
1856 }
1857 if (null === $input->getOption('dir')) {
1858 $input->setOption('dir', $config->get('archive-dir'));
1859 }
1860
1861 $returnCode = $this->archive(
1862 $this->getIO(),
1863 $config,
1864 $input->getArgument('package'),
1865 $input->getArgument('version'),
1866 $input->getOption('format'),
1867 $input->getOption('dir'),
1868 $input->getOption('file'),
1869 $input->getOption('ignore-filters'),
1870 $composer
1871 );
1872
1873 if (0 === $returnCode && $composer) {
1874 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1875 }
1876
1877 return $returnCode;
1878 }
1879
1880 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1881 {
1882 if ($composer) {
1883 $archiveManager = $composer->getArchiveManager();
1884 } else {
1885 $factory = new Factory;
1886 $downloadManager = $factory->createDownloadManager($io, $config);
1887 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1888 }
1889
1890 if ($packageName) {
1891 $package = $this->selectPackage($io, $packageName, $version);
1892
1893 if (!$package) {
1894 return 1;
1895 }
1896 } else {
1897 $package = $this->getComposer()->getPackage();
1898 }
1899
1900 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1901 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1902 $fs = new Filesystem;
1903 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1904
1905 $io->writeError('Created: ', false);
1906 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1907
1908 return 0;
1909 }
1910
1911 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1912 {
1913 $io->writeError('<info>Searching for the specified package.</info>');
1914
1915 if ($composer = $this->getComposer(false)) {
1916 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1917 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1918 } else {
1919 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1920 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1921 $repo = new CompositeRepository($defaultRepos);
1922 }
1923
1924 $packages = $repo->findPackages($packageName, $version);
1925
1926 if (count($packages) > 1) {
1927 $package = reset($packages);
1928 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1929 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1930 return $p->getPrettyString();
1931 }, $packages)).'.');
1932 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1933 } elseif ($packages) {
1934 $package = reset($packages);
1935 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1936 } else {
1937 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1938
1939 return false;
1940 }
1941
1942 return $package;
1943 }
1944 }
1945 <?php
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957 namespace Composer\Command;
1958
1959 use Composer\Composer;
1960 use Composer\Config;
1961 use Composer\Console\Application;
1962 use Composer\Factory;
1963 use Composer\IO\IOInterface;
1964 use Composer\IO\NullIO;
1965 use Composer\Plugin\PreCommandRunEvent;
1966 use Composer\Plugin\PluginEvents;
1967 use Symfony\Component\Console\Input\InputInterface;
1968 use Symfony\Component\Console\Output\OutputInterface;
1969 use Symfony\Component\Console\Command\Command;
1970
1971
1972
1973
1974
1975
1976
1977 abstract class BaseCommand extends Command
1978 {
1979
1980
1981
1982 private $composer;
1983
1984
1985
1986
1987 private $io;
1988
1989
1990
1991
1992
1993
1994
1995 public function getComposer($required = true, $disablePlugins = null)
1996 {
1997 if (null === $this->composer) {
1998 $application = $this->getApplication();
1999 if ($application instanceof Application) {
2000
2001 $this->composer = $application->getComposer($required, $disablePlugins);
2002 } elseif ($required) {
2003 throw new \RuntimeException(
2004 'Could not create a Composer\Composer instance, you must inject '.
2005 'one if this command is not used with a Composer\Console\Application instance'
2006 );
2007 }
2008 }
2009
2010 return $this->composer;
2011 }
2012
2013
2014
2015
2016 public function setComposer(Composer $composer)
2017 {
2018 $this->composer = $composer;
2019 }
2020
2021
2022
2023
2024 public function resetComposer()
2025 {
2026 $this->composer = null;
2027 $this->getApplication()->resetComposer();
2028 }
2029
2030
2031
2032
2033
2034
2035
2036
2037 public function isProxyCommand()
2038 {
2039 return false;
2040 }
2041
2042
2043
2044
2045 public function getIO()
2046 {
2047 if (null === $this->io) {
2048 $application = $this->getApplication();
2049 if ($application instanceof Application) {
2050
2051 $this->io = $application->getIO();
2052 } else {
2053 $this->io = new NullIO();
2054 }
2055 }
2056
2057 return $this->io;
2058 }
2059
2060
2061
2062
2063 public function setIO(IOInterface $io)
2064 {
2065 $this->io = $io;
2066 }
2067
2068
2069
2070
2071 protected function initialize(InputInterface $input, OutputInterface $output)
2072 {
2073
2074 $disablePlugins = $input->hasParameterOption('--no-plugins');
2075 $composer = $this->getComposer(false, $disablePlugins);
2076 if (null === $composer) {
2077 $composer = Factory::createGlobal($this->getIO(), $disablePlugins);
2078 }
2079 if ($composer) {
2080 $preCommandRunEvent = new PreCommandRunEvent(PluginEvents::PRE_COMMAND_RUN, $input, $this->getName());
2081 $composer->getEventDispatcher()->dispatch($preCommandRunEvent->getName(), $preCommandRunEvent);
2082 }
2083
2084 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
2085 $input->setOption('no-progress', true);
2086 }
2087
2088 parent::initialize($input, $output);
2089 }
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
2101 {
2102 $preferSource = false;
2103 $preferDist = false;
2104
2105 switch ($config->get('preferred-install')) {
2106 case 'source':
2107 $preferSource = true;
2108 break;
2109 case 'dist':
2110 $preferDist = true;
2111 break;
2112 case 'auto':
2113 default:
2114
2115 break;
2116 }
2117
2118 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
2119 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
2120 $preferDist = $input->getOption('prefer-dist');
2121 }
2122
2123 return array($preferSource, $preferDist);
2124 }
2125 }
2126 <?php
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138 namespace Composer\Command;
2139
2140 use Composer\DependencyResolver\Pool;
2141 use Composer\Package\Link;
2142 use Composer\Package\PackageInterface;
2143 use Composer\Repository\ArrayRepository;
2144 use Composer\Repository\CompositeRepository;
2145 use Composer\Repository\PlatformRepository;
2146 use Composer\Repository\RepositoryFactory;
2147 use Composer\Plugin\CommandEvent;
2148 use Composer\Plugin\PluginEvents;
2149 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
2150 use Composer\Package\Version\VersionParser;
2151 use Symfony\Component\Console\Helper\Table;
2152 use Symfony\Component\Console\Input\InputArgument;
2153 use Symfony\Component\Console\Input\InputInterface;
2154 use Symfony\Component\Console\Input\InputOption;
2155 use Symfony\Component\Console\Output\OutputInterface;
2156
2157
2158
2159
2160
2161
2162 class BaseDependencyCommand extends BaseCommand
2163 {
2164 const ARGUMENT_PACKAGE = 'package';
2165 const ARGUMENT_CONSTRAINT = 'constraint';
2166 const OPTION_RECURSIVE = 'recursive';
2167 const OPTION_TREE = 'tree';
2168
2169 protected $colors;
2170
2171
2172
2173
2174 protected function configure()
2175 {
2176 $this->setDefinition(array(
2177 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
2178 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
2179 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
2180 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
2181 ));
2182 }
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
2193 {
2194
2195 $composer = $this->getComposer();
2196 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
2197 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
2198
2199
2200 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
2201 $repository = new CompositeRepository(array(
2202 new ArrayRepository(array($composer->getPackage())),
2203 $composer->getRepositoryManager()->getLocalRepository(),
2204 new PlatformRepository(array(), $platformOverrides),
2205 ));
2206 $pool = new Pool();
2207 $pool->addRepository($repository);
2208
2209
2210 list($needle, $textConstraint) = array_pad(
2211 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
2212 2,
2213 $input->getArgument(self::ARGUMENT_CONSTRAINT)
2214 );
2215
2216
2217 $packages = $pool->whatProvides(strtolower($needle));
2218 if (empty($packages)) {
2219 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
2220 }
2221
2222
2223
2224 if (!$repository->findPackage($needle, $textConstraint)) {
2225 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2226 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2227 $repository->addRepository(new ArrayRepository(array(clone $match)));
2228 }
2229 }
2230
2231
2232 $needles = array($needle);
2233 if ($inverted) {
2234 foreach ($packages as $package) {
2235 $needles = array_merge($needles, array_map(function (Link $link) {
2236 return $link->getTarget();
2237 }, $package->getReplaces()));
2238 }
2239 }
2240
2241
2242 if ('*' !== $textConstraint) {
2243 $versionParser = new VersionParser();
2244 $constraint = $versionParser->parseConstraints($textConstraint);
2245 } else {
2246 $constraint = null;
2247 }
2248
2249
2250 $renderTree = $input->getOption(self::OPTION_TREE);
2251 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2252
2253
2254 $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2255 if (empty($results)) {
2256 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2257 $this->getIO()->writeError(sprintf(
2258 '<info>There is no installed package depending on "%s"%s</info>',
2259 $needle,
2260 $extra
2261 ));
2262 } elseif ($renderTree) {
2263 $this->initStyles($output);
2264 $root = $packages[0];
2265 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2266 $this->printTree($results);
2267 } else {
2268 $this->printTable($output, $results);
2269 }
2270
2271 return 0;
2272 }
2273
2274
2275
2276
2277
2278
2279
2280 protected function printTable(OutputInterface $output, $results)
2281 {
2282 $table = array();
2283 $doubles = array();
2284 do {
2285 $queue = array();
2286 $rows = array();
2287 foreach ($results as $result) {
2288
2289
2290
2291
2292 list($package, $link, $children) = $result;
2293 $unique = (string) $link;
2294 if (isset($doubles[$unique])) {
2295 continue;
2296 }
2297 $doubles[$unique] = true;
2298 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2299 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2300 if ($children) {
2301 $queue = array_merge($queue, $children);
2302 }
2303 }
2304 $results = $queue;
2305 $table = array_merge($rows, $table);
2306 } while (!empty($results));
2307
2308
2309 $renderer = new Table($output);
2310 $renderer->setStyle('compact');
2311 $rendererStyle = $renderer->getStyle();
2312 if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
2313 $rendererStyle->setVerticalBorderChars('');
2314 } else {
2315 $rendererStyle->setVerticalBorderChar('');
2316 }
2317 $rendererStyle->setCellRowContentFormat('%s  ');
2318 $renderer->setRows($table)->render();
2319 }
2320
2321
2322
2323
2324
2325
2326 protected function initStyles(OutputInterface $output)
2327 {
2328 $this->colors = array(
2329 'green',
2330 'yellow',
2331 'cyan',
2332 'magenta',
2333 'blue',
2334 );
2335
2336 foreach ($this->colors as $color) {
2337 $style = new OutputFormatterStyle($color);
2338 $output->getFormatter()->setStyle($color, $style);
2339 }
2340 }
2341
2342
2343
2344
2345
2346
2347
2348
2349 protected function printTree($results, $prefix = '', $level = 1)
2350 {
2351 $count = count($results);
2352 $idx = 0;
2353 foreach ($results as $result) {
2354
2355
2356
2357
2358
2359 list($package, $link, $children) = $result;
2360
2361 $color = $this->colors[$level % count($this->colors)];
2362 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2363 $isLast = (++$idx == $count);
2364 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2365 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2366 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2367 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2368 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2369 if ($children) {
2370 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2371 }
2372 }
2373 }
2374
2375 private function writeTreeLine($line)
2376 {
2377 $io = $this->getIO();
2378 if (!$io->isDecorated()) {
2379 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2380 }
2381
2382 $io->write($line);
2383 }
2384 }
2385 <?php
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397 namespace Composer\Command;
2398
2399 use Composer\Package\Link;
2400 use Composer\Package\PackageInterface;
2401 use Composer\Semver\Constraint\Constraint;
2402 use Symfony\Component\Console\Helper\Table;
2403 use Symfony\Component\Console\Input\InputInterface;
2404 use Symfony\Component\Console\Input\InputOption;
2405 use Symfony\Component\Console\Output\OutputInterface;
2406 use Composer\Repository\PlatformRepository;
2407
2408 class CheckPlatformReqsCommand extends BaseCommand
2409 {
2410 protected function configure()
2411 {
2412 $this->setName('check-platform-reqs')
2413 ->setDescription('Check that platform requirements are satisfied.')
2414 ->setDefinition(array(
2415 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables checking of require-dev packages requirements.'),
2416 ))
2417 ->setHelp(
2418 <<<EOT
2419 Checks that your PHP and extensions versions match the platform requirements of the installed packages.
2420
2421 Unlike update/install, this command will ignore config.platform settings and check the real platform packages so you can be certain you have the required platform dependencies.
2422
2423 <info>php composer.phar check-platform-reqs</info>
2424
2425 EOT
2426 );
2427 }
2428
2429 protected function execute(InputInterface $input, OutputInterface $output)
2430 {
2431 $composer = $this->getComposer();
2432
2433 $requires = $composer->getPackage()->getRequires();
2434 if ($input->getOption('no-dev')) {
2435 $dependencies = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'))->getPackages();
2436 } else {
2437 $dependencies = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
2438
2439 if (!$dependencies) {
2440 $dependencies = $composer->getLocker()->getLockedRepository(true)->getPackages();
2441 }
2442 $requires += $composer->getPackage()->getDevRequires();
2443 }
2444 foreach ($requires as $require => $link) {
2445 $requires[$require] = array($link);
2446 }
2447
2448 foreach ($dependencies as $package) {
2449 foreach ($package->getRequires() as $require => $link) {
2450 $requires[$require][] = $link;
2451 }
2452 }
2453
2454 ksort($requires);
2455
2456 $platformRepo = new PlatformRepository(array(), array());
2457 $currentPlatformPackages = $platformRepo->getPackages();
2458 $currentPlatformPackageMap = array();
2459
2460
2461
2462
2463 foreach ($currentPlatformPackages as $currentPlatformPackage) {
2464 $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
2465 }
2466
2467 $results = array();
2468
2469 $exitCode = 0;
2470
2471
2472
2473
2474 foreach ($requires as $require => $links) {
2475 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
2476 if (isset($currentPlatformPackageMap[$require])) {
2477 $pass = true;
2478 $version = $currentPlatformPackageMap[$require]->getVersion();
2479
2480 foreach ($links as $link) {
2481 if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
2482 $results[] = array(
2483 $currentPlatformPackageMap[$require]->getPrettyName(),
2484 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2485 $link,
2486 '<error>failed</error>',
2487 );
2488 $pass = false;
2489
2490 $exitCode = max($exitCode, 1);
2491 }
2492 }
2493
2494 if ($pass) {
2495 $results[] = array(
2496 $currentPlatformPackageMap[$require]->getPrettyName(),
2497 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2498 null,
2499 '<info>success</info>',
2500 );
2501 }
2502 } else {
2503 $results[] = array(
2504 $require,
2505 'n/a',
2506 $links[0],
2507 '<error>missing</error>',
2508 );
2509
2510 $exitCode = max($exitCode, 2);
2511 }
2512 }
2513 }
2514
2515 $this->printTable($output, $results);
2516
2517 return $exitCode;
2518 }
2519
2520 protected function printTable(OutputInterface $output, $results)
2521 {
2522 $table = array();
2523 $rows = array();
2524 foreach ($results as $result) {
2525
2526
2527
2528 list($platformPackage, $version, $link, $status) = $result;
2529 $rows[] = array(
2530 $platformPackage,
2531 $version,
2532 $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '',
2533 $status,
2534 );
2535 }
2536 $table = array_merge($rows, $table);
2537
2538
2539 $renderer = new Table($output);
2540 $renderer->setStyle('compact');
2541 $rendererStyle = $renderer->getStyle();
2542 if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
2543 $rendererStyle->setVerticalBorderChars('');
2544 } else {
2545 $rendererStyle->setVerticalBorderChar('');
2546 }
2547 $rendererStyle->setCellRowContentFormat('%s  ');
2548 $renderer->setRows($table)->render();
2549 }
2550 }
2551 <?php
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563 namespace Composer\Command;
2564
2565 use Composer\Cache;
2566 use Composer\Factory;
2567 use Symfony\Component\Console\Input\InputInterface;
2568 use Symfony\Component\Console\Output\OutputInterface;
2569
2570
2571
2572
2573 class ClearCacheCommand extends BaseCommand
2574 {
2575 protected function configure()
2576 {
2577 $this
2578 ->setName('clear-cache')
2579 ->setAliases(array('clearcache', 'cc'))
2580 ->setDescription('Clears composer\'s internal package cache.')
2581 ->setHelp(
2582 <<<EOT
2583 The <info>clear-cache</info> deletes all cached packages from composer's
2584 cache directory.
2585
2586 Read more at https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-cc
2587 EOT
2588 )
2589 ;
2590 }
2591
2592 protected function execute(InputInterface $input, OutputInterface $output)
2593 {
2594 $config = Factory::createConfig();
2595 $io = $this->getIO();
2596
2597 $cachePaths = array(
2598 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2599 'cache-repo-dir' => $config->get('cache-repo-dir'),
2600 'cache-files-dir' => $config->get('cache-files-dir'),
2601 'cache-dir' => $config->get('cache-dir'),
2602 );
2603
2604 foreach ($cachePaths as $key => $cachePath) {
2605 $cachePath = realpath($cachePath);
2606 if (!$cachePath) {
2607 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2608
2609 continue;
2610 }
2611 $cache = new Cache($io, $cachePath);
2612 if (!$cache->isEnabled()) {
2613 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2614
2615 continue;
2616 }
2617
2618 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2619 $cache->clear();
2620 }
2621
2622 $io->writeError('<info>All caches cleared.</info>');
2623
2624 return 0;
2625 }
2626 }
2627 <?php
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639 namespace Composer\Command;
2640
2641 use Composer\Util\Platform;
2642 use Composer\Util\Silencer;
2643 use Symfony\Component\Console\Input\InputInterface;
2644 use Symfony\Component\Console\Input\InputArgument;
2645 use Symfony\Component\Console\Input\InputOption;
2646 use Symfony\Component\Console\Output\OutputInterface;
2647 use Composer\Config;
2648 use Composer\Config\JsonConfigSource;
2649 use Composer\Factory;
2650 use Composer\IO\IOInterface;
2651 use Composer\Json\JsonFile;
2652 use Composer\Semver\VersionParser;
2653 use Composer\Package\BasePackage;
2654
2655
2656
2657
2658
2659 class ConfigCommand extends BaseCommand
2660 {
2661
2662
2663
2664 protected $config;
2665
2666
2667
2668
2669 protected $configFile;
2670
2671
2672
2673
2674 protected $configSource;
2675
2676
2677
2678
2679 protected $authConfigFile;
2680
2681
2682
2683
2684 protected $authConfigSource;
2685
2686
2687
2688
2689 protected function configure()
2690 {
2691 $this
2692 ->setName('config')
2693 ->setDescription('Sets config options.')
2694 ->setDefinition(array(
2695 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2696 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2697 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2698 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2699 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2700 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2701 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2702 new InputArgument('setting-key', null, 'Setting key'),
2703 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2704 ))
2705 ->setHelp(
2706 <<<EOT
2707 This command allows you to edit composer config settings and repositories
2708 in either the local composer.json file or the global config.json file.
2709
2710 Additionally it lets you edit most properties in the local composer.json.
2711
2712 To set a config setting:
2713
2714     <comment>%command.full_name% bin-dir bin/</comment>
2715
2716 To read a config setting:
2717
2718     <comment>%command.full_name% bin-dir</comment>
2719     Outputs: <info>bin</info>
2720
2721 To edit the global config.json file:
2722
2723     <comment>%command.full_name% --global</comment>
2724
2725 To add a repository:
2726
2727     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2728
2729 To remove a repository (repo is a short alias for repositories):
2730
2731     <comment>%command.full_name% --unset repo.foo</comment>
2732
2733 To disable packagist:
2734
2735     <comment>%command.full_name% repo.packagist false</comment>
2736
2737 You can alter repositories in the global config.json file by passing in the
2738 <info>--global</info> option.
2739
2740 To add or edit suggested packages you can use:
2741
2742     <comment>%command.full_name% suggest.package reason for the suggestion</comment>
2743
2744 To add or edit extra properties you can use:
2745
2746     <comment>%command.full_name% extra.property value</comment>
2747
2748 To edit the file in an external editor:
2749
2750     <comment>%command.full_name% --editor</comment>
2751
2752 To choose your editor you can set the "EDITOR" env variable.
2753
2754 To get a list of configuration values in the file:
2755
2756     <comment>%command.full_name% --list</comment>
2757
2758 You can always pass more than one option. As an example, if you want to edit the
2759 global config.json file.
2760
2761     <comment>%command.full_name% --editor --global</comment>
2762
2763 Read more at https://getcomposer.org/doc/03-cli.md#config
2764 EOT
2765 )
2766 ;
2767 }
2768
2769
2770
2771
2772 protected function initialize(InputInterface $input, OutputInterface $output)
2773 {
2774 parent::initialize($input, $output);
2775
2776 if ($input->getOption('global') && null !== $input->getOption('file')) {
2777 throw new \RuntimeException('--file and --global can not be combined');
2778 }
2779
2780 $io = $this->getIO();
2781 $this->config = Factory::createConfig($io);
2782
2783
2784
2785 $configFile = $input->getOption('global')
2786 ? ($this->config->get('home') . '/config.json')
2787 : ($input->getOption('file') ?: Factory::getComposerFile());
2788
2789
2790 if (
2791 ($configFile === 'composer.json' || $configFile === './composer.json')
2792 && !file_exists($configFile)
2793 && realpath(getcwd()) === realpath($this->config->get('home'))
2794 ) {
2795 file_put_contents($configFile, "{\n}\n");
2796 }
2797
2798 $this->configFile = new JsonFile($configFile, null, $io);
2799 $this->configSource = new JsonConfigSource($this->configFile);
2800
2801 $authConfigFile = $input->getOption('global')
2802 ? ($this->config->get('home') . '/auth.json')
2803 : dirname(realpath($configFile)) . '/auth.json';
2804
2805 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2806 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2807
2808
2809 if ($input->getOption('global') && !$this->configFile->exists()) {
2810 touch($this->configFile->getPath());
2811 $this->configFile->write(array('config' => new \ArrayObject));
2812 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2813 }
2814 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2815 touch($this->authConfigFile->getPath());
2816 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject, 'bearer' => new \ArrayObject));
2817 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2818 }
2819
2820 if (!$this->configFile->exists()) {
2821 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2822 }
2823 }
2824
2825
2826
2827
2828 protected function execute(InputInterface $input, OutputInterface $output)
2829 {
2830
2831 if ($input->getOption('editor')) {
2832 $editor = escapeshellcmd(getenv('EDITOR'));
2833 if (!$editor) {
2834 if (Platform::isWindows()) {
2835 $editor = 'notepad';
2836 } else {
2837 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2838 if (exec('which '.$candidate)) {
2839 $editor = $candidate;
2840 break;
2841 }
2842 }
2843 }
2844 }
2845
2846 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2847 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2848
2849 return 0;
2850 }
2851
2852 if (!$input->getOption('global')) {
2853 $this->config->merge($this->configFile->read());
2854 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2855 }
2856
2857
2858 if ($input->getOption('list')) {
2859 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2860
2861 return 0;
2862 }
2863
2864 $settingKey = $input->getArgument('setting-key');
2865 if (!$settingKey) {
2866 return 0;
2867 }
2868
2869
2870 if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2871 throw new \RuntimeException('You can not combine a setting value with --unset');
2872 }
2873
2874
2875 if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2876 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2877 $rawData = $this->configFile->read();
2878 $data = $this->config->all();
2879 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2880 if (!isset($matches[1]) || $matches[1] === '') {
2881 $value = isset($data['repositories']) ? $data['repositories'] : array();
2882 } else {
2883 if (!isset($data['repositories'][$matches[1]])) {
2884 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2885 }
2886
2887 $value = $data['repositories'][$matches[1]];
2888 }
2889 } elseif (strpos($settingKey, '.')) {
2890 $bits = explode('.', $settingKey);
2891 if ($bits[0] === 'extra') {
2892 $data = $rawData;
2893 } else {
2894 $data = $data['config'];
2895 }
2896 $match = false;
2897 foreach ($bits as $bit) {
2898 $key = isset($key) ? $key.'.'.$bit : $bit;
2899 $match = false;
2900 if (isset($data[$key])) {
2901 $match = true;
2902 $data = $data[$key];
2903 unset($key);
2904 }
2905 }
2906
2907 if (!$match) {
2908 throw new \RuntimeException($settingKey.' is not defined.');
2909 }
2910
2911 $value = $data;
2912 } elseif (isset($data['config'][$settingKey])) {
2913 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2914 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2915 $value = $rawData[$settingKey];
2916 } else {
2917 throw new \RuntimeException($settingKey.' is not defined');
2918 }
2919
2920 if (is_array($value)) {
2921 $value = json_encode($value);
2922 }
2923
2924 $this->getIO()->write($value, true, IOInterface::QUIET);
2925
2926 return 0;
2927 }
2928
2929 $values = $input->getArgument('setting-value'); 
2930
2931 $booleanValidator = function ($val) {
2932 return in_array($val, array('true', 'false', '1', '0'), true);
2933 };
2934 $booleanNormalizer = function ($val) {
2935 return $val !== 'false' && (bool) $val;
2936 };
2937
2938
2939 $uniqueConfigValues = array(
2940 'process-timeout' => array('is_numeric', 'intval'),
2941 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2942 'use-github-api' => array($booleanValidator, $booleanNormalizer),
2943 'preferred-install' => array(
2944 function ($val) {
2945 return in_array($val, array('auto', 'source', 'dist'), true);
2946 },
2947 function ($val) {
2948 return $val;
2949 },
2950 ),
2951 'store-auths' => array(
2952 function ($val) {
2953 return in_array($val, array('true', 'false', 'prompt'), true);
2954 },
2955 function ($val) {
2956 if ('prompt' === $val) {
2957 return 'prompt';
2958 }
2959
2960 return $val !== 'false' && (bool) $val;
2961 },
2962 ),
2963 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2964 'vendor-dir' => array('is_string', function ($val) {
2965 return $val;
2966 }),
2967 'bin-dir' => array('is_string', function ($val) {
2968 return $val;
2969 }),
2970 'archive-dir' => array('is_string', function ($val) {
2971 return $val;
2972 }),
2973 'archive-format' => array('is_string', function ($val) {
2974 return $val;
2975 }),
2976 'data-dir' => array('is_string', function ($val) {
2977 return $val;
2978 }),
2979 'cache-dir' => array('is_string', function ($val) {
2980 return $val;
2981 }),
2982 'cache-files-dir' => array('is_string', function ($val) {
2983 return $val;
2984 }),
2985 'cache-repo-dir' => array('is_string', function ($val) {
2986 return $val;
2987 }),
2988 'cache-vcs-dir' => array('is_string', function ($val) {
2989 return $val;
2990 }),
2991 'cache-ttl' => array('is_numeric', 'intval'),
2992 'cache-files-ttl' => array('is_numeric', 'intval'),
2993 'cache-files-maxsize' => array(
2994 function ($val) {
2995 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2996 },
2997 function ($val) {
2998 return $val;
2999 },
3000 ),
3001 'bin-compat' => array(
3002 function ($val) {
3003 return in_array($val, array('auto', 'full'));
3004 },
3005 function ($val) {
3006 return $val;
3007 },
3008 ),
3009 'discard-changes' => array(
3010 function ($val) {
3011 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
3012 },
3013 function ($val) {
3014 if ('stash' === $val) {
3015 return 'stash';
3016 }
3017
3018 return $val !== 'false' && (bool) $val;
3019 },
3020 ),
3021 'autoloader-suffix' => array('is_string', function ($val) {
3022 return $val === 'null' ? null : $val;
3023 }),
3024 'sort-packages' => array($booleanValidator, $booleanNormalizer),
3025 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
3026 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
3027 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
3028 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
3029 'disable-tls' => array($booleanValidator, $booleanNormalizer),
3030 'secure-http' => array($booleanValidator, $booleanNormalizer),
3031 'cafile' => array(
3032 function ($val) {
3033 return file_exists($val) && is_readable($val);
3034 },
3035 function ($val) {
3036 return $val === 'null' ? null : $val;
3037 },
3038 ),
3039 'capath' => array(
3040 function ($val) {
3041 return is_dir($val) && is_readable($val);
3042 },
3043 function ($val) {
3044 return $val === 'null' ? null : $val;
3045 },
3046 ),
3047 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
3048 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
3049 'lock' => array($booleanValidator, $booleanNormalizer),
3050 );
3051 $multiConfigValues = array(
3052 'github-protocols' => array(
3053 function ($vals) {
3054 if (!is_array($vals)) {
3055 return 'array expected';
3056 }
3057
3058 foreach ($vals as $val) {
3059 if (!in_array($val, array('git', 'https', 'ssh'))) {
3060 return 'valid protocols include: git, https, ssh';
3061 }
3062 }
3063
3064 return true;
3065 },
3066 function ($vals) {
3067 return $vals;
3068 },
3069 ),
3070 'github-domains' => array(
3071 function ($vals) {
3072 if (!is_array($vals)) {
3073 return 'array expected';
3074 }
3075
3076 return true;
3077 },
3078 function ($vals) {
3079 return $vals;
3080 },
3081 ),
3082 'gitlab-domains' => array(
3083 function ($vals) {
3084 if (!is_array($vals)) {
3085 return 'array expected';
3086 }
3087
3088 return true;
3089 },
3090 function ($vals) {
3091 return $vals;
3092 },
3093 ),
3094 );
3095
3096 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
3097 if ($settingKey === 'disable-tls' && $this->config->get('disable-tls')) {
3098 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
3099 }
3100
3101 $this->configSource->removeConfigSetting($settingKey);
3102
3103 return 0;
3104 }
3105 if (isset($uniqueConfigValues[$settingKey])) {
3106 $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
3107
3108 return 0;
3109 }
3110 if (isset($multiConfigValues[$settingKey])) {
3111 $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
3112
3113 return 0;
3114 }
3115
3116 if (preg_match('/^preferred-install\.(.+)/', $settingKey, $matches)) {
3117 if ($input->getOption('unset')) {
3118 $this->configSource->removeConfigSetting($settingKey);
3119
3120 return 0;
3121 }
3122
3123 list($validator) = $uniqueConfigValues['preferred-install'];
3124 if (!$validator($values[0])) {
3125 throw new \RuntimeException('Invalid value for '.$settingKey.'. Should be one of: auto, source, or dist');
3126 }
3127
3128 $this->configSource->addConfigSetting($settingKey, $values[0]);
3129
3130 return 0;
3131 }
3132
3133
3134 $uniqueProps = array(
3135 'name' => array('is_string', function ($val) {
3136 return $val;
3137 }),
3138 'type' => array('is_string', function ($val) {
3139 return $val;
3140 }),
3141 'description' => array('is_string', function ($val) {
3142 return $val;
3143 }),
3144 'homepage' => array('is_string', function ($val) {
3145 return $val;
3146 }),
3147 'version' => array('is_string', function ($val) {
3148 return $val;
3149 }),
3150 'minimum-stability' => array(
3151 function ($val) {
3152 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
3153 },
3154 function ($val) {
3155 return VersionParser::normalizeStability($val);
3156 },
3157 ),
3158 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
3159 );
3160 $multiProps = array(
3161 'keywords' => array(
3162 function ($vals) {
3163 if (!is_array($vals)) {
3164 return 'array expected';
3165 }
3166
3167 return true;
3168 },
3169 function ($vals) {
3170 return $vals;
3171 },
3172 ),
3173 'license' => array(
3174 function ($vals) {
3175 if (!is_array($vals)) {
3176 return 'array expected';
3177 }
3178
3179 return true;
3180 },
3181 function ($vals) {
3182 return $vals;
3183 },
3184 ),
3185 );
3186
3187 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
3188 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');
3189 }
3190 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
3191 $this->configSource->removeProperty($settingKey);
3192
3193 return 0;
3194 }
3195 if (isset($uniqueProps[$settingKey])) {
3196 $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
3197
3198 return 0;
3199 }
3200 if (isset($multiProps[$settingKey])) {
3201 $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
3202
3203 return 0;
3204 }
3205
3206
3207 if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
3208 if ($input->getOption('unset')) {
3209 $this->configSource->removeRepository($matches[1]);
3210
3211 return 0;
3212 }
3213
3214 if (2 === count($values)) {
3215 $this->configSource->addRepository($matches[1], array(
3216 'type' => $values[0],
3217 'url' => $values[1],
3218 ));
3219
3220 return 0;
3221 }
3222
3223 if (1 === count($values)) {
3224 $value = strtolower($values[0]);
3225 if (true === $booleanValidator($value)) {
3226 if (false === $booleanNormalizer($value)) {
3227 $this->configSource->addRepository($matches[1], false);
3228
3229 return 0;
3230 }
3231 } else {
3232 $value = JsonFile::parseJson($values[0]);
3233 $this->configSource->addRepository($matches[1], $value);
3234
3235 return 0;
3236 }
3237 }
3238
3239 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
3240 }
3241
3242
3243 if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
3244 if ($input->getOption('unset')) {
3245 $this->configSource->removeProperty($settingKey);
3246
3247 return 0;
3248 }
3249
3250 $this->configSource->addProperty($settingKey, $values[0]);
3251
3252 return 0;
3253 }
3254
3255
3256 if (preg_match('/^suggest\.(.+)/', $settingKey, $matches)) {
3257 if ($input->getOption('unset')) {
3258 $this->configSource->removeProperty($settingKey);
3259
3260 return 0;
3261 }
3262
3263 $this->configSource->addProperty($settingKey, implode(' ', $values));
3264
3265 return 0;
3266 }
3267
3268
3269 if (in_array($settingKey, array('suggest', 'extra'), true) && $input->getOption('unset')) {
3270 $this->configSource->removeProperty($settingKey);
3271
3272 return 0;
3273 }
3274
3275
3276 if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
3277 if ($input->getOption('unset')) {
3278 $this->configSource->removeConfigSetting($settingKey);
3279
3280 return 0;
3281 }
3282
3283 $this->configSource->addConfigSetting($settingKey, $values[0]);
3284
3285 return 0;
3286 }
3287
3288
3289 if ($settingKey === 'platform' && $input->getOption('unset')) {
3290 $this->configSource->removeConfigSetting($settingKey);
3291
3292 return 0;
3293 }
3294
3295
3296 if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|bearer)\.(.+)/', $settingKey, $matches)) {
3297 if ($input->getOption('unset')) {
3298 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3299 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3300
3301 return 0;
3302 }
3303
3304 if ($matches[1] === 'bitbucket-oauth') {
3305 if (2 !== count($values)) {
3306 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
3307 }
3308 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3309 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
3310 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token', 'bearer'), true)) {
3311 if (1 !== count($values)) {
3312 throw new \RuntimeException('Too many arguments, expected only one token');
3313 }
3314 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3315 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
3316 } elseif ($matches[1] === 'http-basic') {
3317 if (2 !== count($values)) {
3318 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
3319 }
3320 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3321 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
3322 }
3323
3324 return 0;
3325 }
3326
3327
3328 if (preg_match('/^scripts\.(.+)/', $settingKey, $matches)) {
3329 if ($input->getOption('unset')) {
3330 $this->configSource->removeProperty($settingKey);
3331
3332 return 0;
3333 }
3334
3335 $this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
3336
3337 return 0;
3338 }
3339
3340 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
3341 }
3342
3343 protected function handleSingleValue($key, array $callbacks, array $values, $method)
3344 {
3345 list($validator, $normalizer) = $callbacks;
3346 if (1 !== count($values)) {
3347 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
3348 }
3349
3350 if (true !== $validation = $validator($values[0])) {
3351 throw new \RuntimeException(sprintf(
3352 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3353 $values[0]
3354 ));
3355 }
3356
3357 $normalizedValue = $normalizer($values[0]);
3358
3359 if ($key === 'disable-tls') {
3360 if (!$normalizedValue && $this->config->get('disable-tls')) {
3361 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
3362 } elseif ($normalizedValue && !$this->config->get('disable-tls')) {
3363 $this->getIO()->writeError('<warning>You are now running Composer with SSL/TLS protection disabled.</warning>');
3364 }
3365 }
3366
3367 return call_user_func(array($this->configSource, $method), $key, $normalizedValue);
3368 }
3369
3370 protected function handleMultiValue($key, array $callbacks, array $values, $method)
3371 {
3372 list($validator, $normalizer) = $callbacks;
3373 if (true !== $validation = $validator($values)) {
3374 throw new \RuntimeException(sprintf(
3375 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3376 json_encode($values)
3377 ));
3378 }
3379
3380 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
3381 }
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
3392 {
3393 $origK = $k;
3394 $io = $this->getIO();
3395 foreach ($contents as $key => $value) {
3396 if ($k === null && !in_array($key, array('config', 'repositories'))) {
3397 continue;
3398 }
3399
3400 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
3401
3402 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
3403 $k .= preg_replace('{^config\.}', '', $key . '.');
3404 $this->listConfiguration($value, $rawVal, $output, $k);
3405 $k = $origK;
3406
3407 continue;
3408 }
3409
3410 if (is_array($value)) {
3411 $value = array_map(function ($val) {
3412 return is_array($val) ? json_encode($val) : $val;
3413 }, $value);
3414
3415 $value = '['.implode(', ', $value).']';
3416 }
3417
3418 if (is_bool($value)) {
3419 $value = var_export($value, true);
3420 }
3421
3422 if (is_string($rawVal) && $rawVal != $value) {
3423 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>', true, IOInterface::QUIET);
3424 } else {
3425 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>', true, IOInterface::QUIET);
3426 }
3427 }
3428 }
3429 }
3430 <?php
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442 namespace Composer\Command;
3443
3444 use Composer\Config;
3445 use Composer\Factory;
3446 use Composer\Installer;
3447 use Composer\Installer\ProjectInstaller;
3448 use Composer\Installer\InstallationManager;
3449 use Composer\Installer\SuggestedPackagesReporter;
3450 use Composer\IO\IOInterface;
3451 use Composer\Package\BasePackage;
3452 use Composer\DependencyResolver\Pool;
3453 use Composer\DependencyResolver\Operation\InstallOperation;
3454 use Composer\Package\Version\VersionSelector;
3455 use Composer\Package\AliasPackage;
3456 use Composer\Repository\RepositoryFactory;
3457 use Composer\Repository\CompositeRepository;
3458 use Composer\Repository\PlatformRepository;
3459 use Composer\Repository\InstalledFilesystemRepository;
3460 use Composer\Script\ScriptEvents;
3461 use Composer\Util\Silencer;
3462 use Symfony\Component\Console\Input\InputArgument;
3463 use Symfony\Component\Console\Input\InputInterface;
3464 use Symfony\Component\Console\Input\InputOption;
3465 use Symfony\Component\Console\Output\OutputInterface;
3466 use Symfony\Component\Finder\Finder;
3467 use Composer\Json\JsonFile;
3468 use Composer\Config\JsonConfigSource;
3469 use Composer\Util\Filesystem;
3470 use Composer\Package\Version\VersionParser;
3471 use Composer\EventDispatcher\EventDispatcher;
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481 class CreateProjectCommand extends BaseCommand
3482 {
3483
3484
3485
3486 protected $suggestedPackagesReporter;
3487
3488 protected function configure()
3489 {
3490 $this
3491 ->setName('create-project')
3492 ->setDescription('Creates new project from a package into given directory.')
3493 ->setDefinition(array(
3494 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
3495 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
3496 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
3497 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
3498 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
3499 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
3500 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
3501 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
3502 new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the repository option to the composer.json.'),
3503 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
3504 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
3505 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
3506 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
3507 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
3508 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.'),
3509 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'),
3510 new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'),
3511 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
3512 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
3513 ))
3514 ->setHelp(
3515 <<<EOT
3516 The <info>create-project</info> command creates a new project from a given
3517 package into a new directory. If executed without params and in a directory
3518 with a composer.json file it installs the packages for the current project.
3519
3520 You can use this command to bootstrap new projects or setup a clean
3521 version-controlled installation for developers of your project.
3522
3523 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3524
3525 You can also specify the version with the package name using = or : as separator.
3526
3527 <info>php composer.phar create-project vendor/project:version target-directory</info>
3528
3529 To install unstable packages, either specify the version you want, or use the
3530 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3531
3532 To setup a developer workable version you should create the project using the source
3533 controlled code by appending the <info>'--prefer-source'</info> flag.
3534
3535 To install a package from another repository than the default one you
3536 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3537
3538 Read more at https://getcomposer.org/doc/03-cli.md#create-project
3539 EOT
3540 )
3541 ;
3542 }
3543
3544 protected function execute(InputInterface $input, OutputInterface $output)
3545 {
3546 $config = Factory::createConfig();
3547 $io = $this->getIO();
3548
3549 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3550
3551 if ($input->getOption('dev')) {
3552 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3553 }
3554 if ($input->getOption('no-custom-installers')) {
3555 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3556 $input->setOption('no-plugins', true);
3557 }
3558
3559 return $this->installProject(
3560 $io,
3561 $config,
3562 $input,
3563 $input->getArgument('package'),
3564 $input->getArgument('directory'),
3565 $input->getArgument('version'),
3566 $input->getOption('stability'),
3567 $preferSource,
3568 $preferDist,
3569 !$input->getOption('no-dev'),
3570 $input->getOption('repository') ?: $input->getOption('repository-url'),
3571 $input->getOption('no-plugins'),
3572 $input->getOption('no-scripts'),
3573 $input->getOption('no-progress'),
3574 $input->getOption('no-install'),
3575 $input->getOption('ignore-platform-reqs'),
3576 !$input->getOption('no-secure-http'),
3577 $input->getOption('add-repository')
3578 );
3579 }
3580
3581 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, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true, $addRepository = false)
3582 {
3583 $oldCwd = getcwd();
3584
3585
3586 $io->loadConfiguration($config);
3587
3588 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3589
3590 if ($packageName !== null) {
3591 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
3592 } else {
3593 $installedFromVcs = false;
3594 }
3595
3596 $composer = Factory::create($io, null, $disablePlugins);
3597
3598
3599 if ($repository !== null && $addRepository) {
3600 if ($composer->getLocker()->isLocked()) {
3601 $io->writeError('<error>Adding a repository when creating a project that provides a composer.lock file is not supported</error>');
3602
3603 return false;
3604 }
3605
3606 $repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repository, true);
3607 $composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories();
3608 $name = RepositoryFactory::generateRepositoryName(0, $repoConfig, $composerJsonRepositoriesConfig);
3609 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3610 $configSource->addRepository($name, $repoConfig);
3611
3612 $composer = Factory::create($io, null, $disablePlugins);
3613 }
3614
3615 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3616
3617 $fs = new Filesystem();
3618
3619 if ($noScripts === false) {
3620
3621 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3622 }
3623
3624
3625 $config = $composer->getConfig();
3626 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3627
3628
3629 if ($noInstall === false) {
3630 $installer = Installer::create($io, $composer);
3631 $installer->setPreferSource($preferSource)
3632 ->setPreferDist($preferDist)
3633 ->setDevMode($installDevPackages)
3634 ->setRunScripts(!$noScripts)
3635 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3636 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3637 ->setOptimizeAutoloader($config->get('optimize-autoloader'))
3638 ->setClassMapAuthoritative($config->get('classmap-authoritative'))
3639 ->setApcuAutoloader($config->get('apcu-autoloader'));
3640
3641 if ($disablePlugins) {
3642 $installer->disablePlugins();
3643 }
3644
3645 $status = $installer->run();
3646 if (0 !== $status) {
3647 return $status;
3648 }
3649 }
3650
3651 $hasVcs = $installedFromVcs;
3652 if (
3653 !$input->getOption('keep-vcs')
3654 && $installedFromVcs
3655 && (
3656 $input->getOption('remove-vcs')
3657 || !$io->isInteractive()
3658 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3659 )
3660 ) {
3661 $finder = new Finder();
3662 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3663 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3664 $finder->name($vcsName);
3665 }
3666
3667 try {
3668 $dirs = iterator_to_array($finder);
3669 unset($finder);
3670 foreach ($dirs as $dir) {
3671 if (!$fs->removeDirectory($dir)) {
3672 throw new \RuntimeException('Could not remove '.$dir);
3673 }
3674 }
3675 } catch (\Exception $e) {
3676 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3677 }
3678
3679 $hasVcs = false;
3680 }
3681
3682
3683 if (!$hasVcs) {
3684 $package = $composer->getPackage();
3685 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3686 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3687 foreach ($package->{'get'.$meta['method']}() as $link) {
3688 if ($link->getPrettyConstraint() === 'self.version') {
3689 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3690 }
3691 }
3692 }
3693 }
3694
3695 if ($noScripts === false) {
3696
3697 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3698 }
3699
3700 chdir($oldCwd);
3701 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3702 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3703 Silencer::call('rmdir', $vendorComposerDir);
3704 $vendorDir = $config->get('vendor-dir');
3705 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3706 Silencer::call('rmdir', $vendorDir);
3707 }
3708 }
3709
3710 return 0;
3711 }
3712
3713 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, $noProgress = false, $ignorePlatformReqs = false, $secureHttp = true)
3714 {
3715 if (!$secureHttp) {
3716 $config->merge(array('config' => array('secure-http' => false)));
3717 }
3718
3719 $composer = Factory::create($io, $config->all(), $disablePlugins);
3720 $config = $composer->getConfig();
3721 $rm = $composer->getRepositoryManager();
3722
3723 if (null === $repository) {
3724 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config, $rm));
3725 } else {
3726 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true, $rm);
3727 }
3728
3729 $parser = new VersionParser();
3730 $requirements = $parser->parseNameVersionPairs(array($packageName));
3731 $name = strtolower($requirements[0]['name']);
3732 if (!$packageVersion && isset($requirements[0]['version'])) {
3733 $packageVersion = $requirements[0]['version'];
3734 }
3735
3736
3737 if (null === $directory) {
3738 $parts = explode("/", $name, 2);
3739 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3740 }
3741
3742 $fs = new Filesystem();
3743 if (!$fs->isAbsolutePath($directory)) {
3744 $directory = getcwd() . DIRECTORY_SEPARATOR . $directory;
3745 }
3746
3747 $io->writeError('<info>Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(getcwd(), $directory, true) . '"</info>');
3748
3749 if (file_exists($directory)) {
3750 if (!is_dir($directory)) {
3751 throw new \InvalidArgumentException('Cannot create project directory at "'.$directory.'", it exists as a file.');
3752 } elseif (!$fs->isDirEmpty($directory)) {
3753 throw new \InvalidArgumentException('Project directory "'.$directory.'" is not empty.');
3754 }
3755 }
3756
3757 if (null === $stability) {
3758 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3759 $stability = $match[1];
3760 } else {
3761 $stability = VersionParser::parseStability($packageVersion);
3762 }
3763 }
3764
3765 $stability = VersionParser::normalizeStability($stability);
3766
3767 if (!isset(BasePackage::$stabilities[$stability])) {
3768 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3769 }
3770
3771 $pool = new Pool($stability);
3772 $pool->addRepository($sourceRepo);
3773
3774 $phpVersion = null;
3775 $prettyPhpVersion = null;
3776 if (!$ignorePlatformReqs) {
3777 $platformOverrides = $config->get('platform') ?: array();
3778
3779 $platform = new PlatformRepository(array(), $platformOverrides);
3780 $phpPackage = $platform->findPackage('php', '*');
3781 $phpVersion = $phpPackage->getVersion();
3782 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3783 }
3784
3785
3786 $versionSelector = new VersionSelector($pool);
3787 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3788
3789 if (!$package) {
3790 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3791 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3792 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3793 }
3794
3795 throw new \InvalidArgumentException($errorMessage .'.');
3796 }
3797
3798
3799 if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
3800 @mkdir($directory, 0777, true);
3801 if ($realDir = realpath($directory)) {
3802 pcntl_async_signals(true);
3803 pcntl_signal(SIGINT, function () use ($realDir) {
3804 $fs = new Filesystem();
3805 $fs->removeDirectory($realDir);
3806 exit(130);
3807 });
3808 }
3809 }
3810
3811 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3812
3813 if ($disablePlugins) {
3814 $io->writeError('<info>Plugins have been disabled.</info>');
3815 }
3816
3817 if ($package instanceof AliasPackage) {
3818 $package = $package->getAliasOf();
3819 }
3820
3821 $dm = $composer->getDownloadManager();
3822 $dm->setPreferSource($preferSource)
3823 ->setPreferDist($preferDist)
3824 ->setOutputProgress(!$noProgress);
3825
3826 $projectInstaller = new ProjectInstaller($directory, $dm);
3827 $im = $composer->getInstallationManager();
3828 $im->addInstaller($projectInstaller);
3829 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3830 $im->notifyInstalls($io);
3831
3832
3833 $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3834
3835 $installedFromVcs = 'source' === $package->getInstallationSource();
3836
3837 $io->writeError('<info>Created project in ' . $directory . '</info>');
3838 chdir($directory);
3839
3840 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3841 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3842
3843 return $installedFromVcs;
3844 }
3845 }
3846 <?php
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858 namespace Composer\Command;
3859
3860 use Symfony\Component\Console\Input\InputInterface;
3861 use Symfony\Component\Console\Output\OutputInterface;
3862
3863
3864
3865
3866 class DependsCommand extends BaseDependencyCommand
3867 {
3868
3869
3870
3871 protected function configure()
3872 {
3873 parent::configure();
3874
3875 $this
3876 ->setName('depends')
3877 ->setAliases(array('why'))
3878 ->setDescription('Shows which packages cause the given package to be installed.')
3879 ->setHelp(
3880 <<<EOT
3881 Displays detailed information about where a package is referenced.
3882
3883 <info>php composer.phar depends composer/composer</info>
3884
3885 Read more at https://getcomposer.org/doc/03-cli.md#depends-why-
3886 EOT
3887 )
3888 ;
3889 }
3890
3891
3892
3893
3894
3895
3896
3897
3898 protected function execute(InputInterface $input, OutputInterface $output)
3899 {
3900 return parent::doExecute($input, $output, false);
3901 }
3902 }
3903 <?php
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915 namespace Composer\Command;
3916
3917 use Composer\Composer;
3918 use Composer\Factory;
3919 use Composer\Config;
3920 use Composer\Downloader\TransportException;
3921 use Composer\Repository\PlatformRepository;
3922 use Composer\Plugin\CommandEvent;
3923 use Composer\Plugin\PluginEvents;
3924 use Composer\Util\ConfigValidator;
3925 use Composer\Util\IniHelper;
3926 use Composer\Util\ProcessExecutor;
3927 use Composer\Util\RemoteFilesystem;
3928 use Composer\Util\StreamContextFactory;
3929 use Composer\SelfUpdate\Keys;
3930 use Composer\SelfUpdate\Versions;
3931 use Composer\IO\NullIO;
3932 use Symfony\Component\Console\Input\InputInterface;
3933 use Symfony\Component\Console\Output\OutputInterface;
3934
3935
3936
3937
3938 class DiagnoseCommand extends BaseCommand
3939 {
3940
3941 protected $rfs;
3942
3943
3944 protected $process;
3945
3946
3947 protected $exitCode = 0;
3948
3949 protected function configure()
3950 {
3951 $this
3952 ->setName('diagnose')
3953 ->setDescription('Diagnoses the system to identify common errors.')
3954 ->setHelp(
3955 <<<EOT
3956 The <info>diagnose</info> command checks common errors to help debugging problems.
3957
3958 The process exit code will be 1 in case of warnings and 2 for errors.
3959
3960 Read more at https://getcomposer.org/doc/03-cli.md#diagnose
3961 EOT
3962 )
3963 ;
3964 }
3965
3966
3967
3968
3969 protected function execute(InputInterface $input, OutputInterface $output)
3970 {
3971 $composer = $this->getComposer(false);
3972 $io = $this->getIO();
3973
3974 if ($composer) {
3975 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3976 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3977
3978 $io->write('Checking composer.json: ', false);
3979 $this->outputResult($this->checkComposerSchema());
3980 }
3981
3982 if ($composer) {
3983 $config = $composer->getConfig();
3984 } else {
3985 $config = Factory::createConfig();
3986 }
3987
3988 $config->merge(array('config' => array('secure-http' => false)));
3989 $config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO);
3990
3991 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3992 $this->process = new ProcessExecutor($io);
3993
3994 $io->write('Checking platform settings: ', false);
3995 $this->outputResult($this->checkPlatform());
3996
3997 $io->write('Checking git settings: ', false);
3998 $this->outputResult($this->checkGit());
3999
4000 $io->write('Checking http connectivity to packagist: ', false);
4001 $this->outputResult($this->checkHttp('http', $config));
4002
4003 $io->write('Checking https connectivity to packagist: ', false);
4004 $this->outputResult($this->checkHttp('https', $config));
4005
4006 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
4007 if (!empty($opts['http']['proxy'])) {
4008 $io->write('Checking HTTP proxy: ', false);
4009 $this->outputResult($this->checkHttpProxy());
4010 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
4011 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
4012 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
4013 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
4014 }
4015
4016 if ($oauth = $config->get('github-oauth')) {
4017 foreach ($oauth as $domain => $token) {
4018 $io->write('Checking '.$domain.' oauth access: ', false);
4019 $this->outputResult($this->checkGithubOauth($domain, $token));
4020 }
4021 } else {
4022 $io->write('Checking github.com rate limit: ', false);
4023 try {
4024 $rate = $this->getGithubRateLimit('github.com');
4025 if (!is_array($rate)) {
4026 $this->outputResult($rate);
4027 } elseif (10 > $rate['remaining']) {
4028 $io->write('<warning>WARNING</warning>');
4029 $io->write(sprintf(
4030 '<comment>Github has a rate limit on their API. '
4031 . 'You currently have <options=bold>%u</options=bold> '
4032 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
4033 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
4034 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
4035 $rate['remaining'],
4036 $rate['limit']
4037 ));
4038 } else {
4039 $this->outputResult(true);
4040 }
4041 } catch (\Exception $e) {
4042 if ($e instanceof TransportException && $e->getCode() === 401) {
4043 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
4044 } else {
4045 $this->outputResult($e);
4046 }
4047 }
4048 }
4049
4050 $io->write('Checking disk free space: ', false);
4051 $this->outputResult($this->checkDiskSpace($config));
4052
4053 if ('phar:' === substr(__FILE__, 0, 5)) {
4054 $io->write('Checking pubkeys: ', false);
4055 $this->outputResult($this->checkPubKeys($config));
4056
4057 $io->write('Checking composer version: ', false);
4058 $this->outputResult($this->checkVersion($config));
4059 }
4060
4061 $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::VERSION));
4062
4063 $platformOverrides = $config->get('platform') ?: array();
4064 $platformRepo = new PlatformRepository(array(), $platformOverrides);
4065 $phpPkg = $platformRepo->findPackage('php', '*');
4066 $phpVersion = $phpPkg->getPrettyVersion();
4067 if (false !== strpos($phpPkg->getDescription(), 'overridden')) {
4068 $phpVersion .= ' - ' . $phpPkg->getDescription();
4069 }
4070
4071 $io->write(sprintf('PHP version: <comment>%s</comment>', $phpVersion));
4072
4073 if (defined('PHP_BINARY')) {
4074 $io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
4075 }
4076
4077 $io->write('OpenSSL version: ' . (defined('OPENSSL_VERSION_TEXT') ? '<comment>'.OPENSSL_VERSION_TEXT.'</comment>' : '<error>missing</error>'));
4078
4079 return $this->exitCode;
4080 }
4081
4082 private function checkComposerSchema()
4083 {
4084 $validator = new ConfigValidator($this->getIO());
4085 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
4086
4087 if ($errors || $warnings) {
4088 $messages = array(
4089 'error' => $errors,
4090 'warning' => $warnings,
4091 );
4092
4093 $output = '';
4094 foreach ($messages as $style => $msgs) {
4095 foreach ($msgs as $msg) {
4096 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
4097 }
4098 }
4099
4100 return rtrim($output);
4101 }
4102
4103 return true;
4104 }
4105
4106 private function checkGit()
4107 {
4108 $this->process->execute('git config color.ui', $output);
4109 if (strtolower(trim($output)) === 'always') {
4110 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>';
4111 }
4112
4113 return true;
4114 }
4115
4116 private function checkHttp($proto, Config $config)
4117 {
4118 $result = $this->checkConnectivity();
4119 if ($result !== true) {
4120 return $result;
4121 }
4122
4123 $disableTls = false;
4124 $result = array();
4125 if ($proto === 'https' && $config->get('disable-tls') === true) {
4126 $disableTls = true;
4127 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
4128 }
4129 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
4130 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
4131 }
4132
4133 try {
4134 $this->rfs->getContents('packagist.org', $proto . '://repo.packagist.org/packages.json', false);
4135 } catch (TransportException $e) {
4136 if (false !== strpos($e->getMessage(), 'cafile')) {
4137 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
4138 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
4139 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
4140 } else {
4141 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
4142 }
4143 }
4144
4145 if (count($result) > 0) {
4146 return $result;
4147 }
4148
4149 return true;
4150 }
4151
4152 private function checkHttpProxy()
4153 {
4154 $result = $this->checkConnectivity();
4155 if ($result !== true) {
4156 return $result;
4157 }
4158
4159 $protocol = extension_loaded('openssl') ? 'https' : 'http';
4160 try {
4161 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/packages.json', false), true);
4162 $hash = reset($json['provider-includes']);
4163 $hash = $hash['sha256'];
4164 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
4165 $provider = $this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/'.$path, false);
4166
4167 if (hash('sha256', $provider) !== $hash) {
4168 return 'It seems that your proxy is modifying http traffic on the fly';
4169 }
4170 } catch (\Exception $e) {
4171 return $e;
4172 }
4173
4174 return true;
4175 }
4176
4177
4178
4179
4180
4181
4182
4183
4184 private function checkHttpProxyFullUriRequestParam()
4185 {
4186 $result = $this->checkConnectivity();
4187 if ($result !== true) {
4188 return $result;
4189 }
4190
4191 $url = 'http://repo.packagist.org/packages.json';
4192 try {
4193 $this->rfs->getContents('packagist.org', $url, false);
4194 } catch (TransportException $e) {
4195 try {
4196 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
4197 } catch (TransportException $e) {
4198 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
4199 }
4200
4201 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"';
4202 }
4203
4204 return true;
4205 }
4206
4207
4208
4209
4210
4211
4212
4213
4214 private function checkHttpsProxyFullUriRequestParam()
4215 {
4216 $result = $this->checkConnectivity();
4217 if ($result !== true) {
4218 return $result;
4219 }
4220
4221 if (!extension_loaded('openssl')) {
4222 return 'You need the openssl extension installed for this check';
4223 }
4224
4225 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
4226 try {
4227 $this->rfs->getContents('github.com', $url, false);
4228 } catch (TransportException $e) {
4229 try {
4230 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
4231 } catch (TransportException $e) {
4232 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
4233 }
4234
4235 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
4236 }
4237
4238 return true;
4239 }
4240
4241 private function checkGithubOauth($domain, $token)
4242 {
4243 $result = $this->checkConnectivity();
4244 if ($result !== true) {
4245 return $result;
4246 }
4247
4248 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
4249 try {
4250 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
4251
4252 return $this->rfs->getContents($domain, $url, false, array(
4253 'retry-auth-failure' => false,
4254 )) ? true : 'Unexpected error';
4255 } catch (\Exception $e) {
4256 if ($e instanceof TransportException && $e->getCode() === 401) {
4257 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
4258 }
4259
4260 return $e;
4261 }
4262 }
4263
4264
4265
4266
4267
4268
4269
4270 private function getGithubRateLimit($domain, $token = null)
4271 {
4272 $result = $this->checkConnectivity();
4273 if ($result !== true) {
4274 return $result;
4275 }
4276
4277 if ($token) {
4278 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
4279 }
4280
4281 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
4282 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
4283 $data = json_decode($json, true);
4284
4285 return $data['resources']['core'];
4286 }
4287
4288 private function checkDiskSpace($config)
4289 {
4290 $minSpaceFree = 1024 * 1024;
4291 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
4292 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
4293 ) {
4294 return '<error>The disk hosting '.$dir.' is full</error>';
4295 }
4296
4297 return true;
4298 }
4299
4300 private function checkPubKeys($config)
4301 {
4302 $home = $config->get('home');
4303 $errors = array();
4304 $io = $this->getIO();
4305
4306 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
4307 $io->write('');
4308 }
4309
4310 if (file_exists($home.'/keys.tags.pub')) {
4311 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
4312 } else {
4313 $errors[] = '<error>Missing pubkey for tags verification</error>';
4314 }
4315
4316 if (file_exists($home.'/keys.dev.pub')) {
4317 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
4318 } else {
4319 $errors[] = '<error>Missing pubkey for dev verification</error>';
4320 }
4321
4322 if ($errors) {
4323 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
4324 }
4325
4326 return $errors ?: true;
4327 }
4328
4329 private function checkVersion($config)
4330 {
4331 $result = $this->checkConnectivity();
4332 if ($result !== true) {
4333 return $result;
4334 }
4335
4336 $versionsUtil = new Versions($config, $this->rfs);
4337 try {
4338 $latest = $versionsUtil->getLatest();
4339 } catch (\Exception $e) {
4340 return $e;
4341 }
4342
4343 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
4344 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
4345 }
4346
4347 return true;
4348 }
4349
4350
4351
4352
4353 private function outputResult($result)
4354 {
4355 $io = $this->getIO();
4356 if (true === $result) {
4357 $io->write('<info>OK</info>');
4358
4359 return;
4360 }
4361
4362 $hadError = false;
4363 $hadWarning = false;
4364 if ($result instanceof \Exception) {
4365 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
4366 }
4367
4368 if (!$result) {
4369
4370 $hadError = true;
4371 } else {
4372 if (!is_array($result)) {
4373 $result = array($result);
4374 }
4375 foreach ($result as $message) {
4376 if (false !== strpos($message, '<error>')) {
4377 $hadError = true;
4378 } elseif (false !== strpos($message, '<warning>')) {
4379 $hadWarning = true;
4380 }
4381 }
4382 }
4383
4384 if ($hadError) {
4385 $io->write('<error>FAIL</error>');
4386 $this->exitCode = max($this->exitCode, 2);
4387 } elseif ($hadWarning) {
4388 $io->write('<warning>WARNING</warning>');
4389 $this->exitCode = max($this->exitCode, 1);
4390 }
4391
4392 if ($result) {
4393 foreach ($result as $message) {
4394 $io->write($message);
4395 }
4396 }
4397 }
4398
4399 private function checkPlatform()
4400 {
4401 $output = '';
4402 $out = function ($msg, $style) use (&$output) {
4403 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
4404 };
4405
4406
4407 $errors = array();
4408 $warnings = array();
4409 $displayIniMessage = false;
4410
4411 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
4412 $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.';
4413
4414 if (!function_exists('json_decode')) {
4415 $errors['json'] = true;
4416 }
4417
4418 if (!extension_loaded('Phar')) {
4419 $errors['phar'] = true;
4420 }
4421
4422 if (!extension_loaded('filter')) {
4423 $errors['filter'] = true;
4424 }
4425
4426 if (!extension_loaded('hash')) {
4427 $errors['hash'] = true;
4428 }
4429
4430 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
4431 $errors['iconv_mbstring'] = true;
4432 }
4433
4434 if (!filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
4435 $errors['allow_url_fopen'] = true;
4436 }
4437
4438 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
4439 $errors['ioncube'] = ioncube_loader_version();
4440 }
4441
4442 if (PHP_VERSION_ID < 50302) {
4443 $errors['php'] = PHP_VERSION;
4444 }
4445
4446 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
4447 $warnings['php'] = PHP_VERSION;
4448 }
4449
4450 if (!extension_loaded('openssl')) {
4451 $errors['openssl'] = true;
4452 }
4453
4454 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
4455 $warnings['openssl_version'] = true;
4456 }
4457
4458 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) {
4459 $warnings['apc_cli'] = true;
4460 }
4461
4462 if (!extension_loaded('zlib')) {
4463 $warnings['zlib'] = true;
4464 }
4465
4466 ob_start();
4467 phpinfo(INFO_GENERAL);
4468 $phpinfo = ob_get_clean();
4469 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
4470 $configure = $match[1];
4471
4472 if (false !== strpos($configure, '--enable-sigchild')) {
4473 $warnings['sigchild'] = true;
4474 }
4475
4476 if (false !== strpos($configure, '--with-curlwrappers')) {
4477 $warnings['curlwrappers'] = true;
4478 }
4479 }
4480
4481 if (filter_var(ini_get('xdebug.profiler_enabled'), FILTER_VALIDATE_BOOLEAN)) {
4482 $warnings['xdebug_profile'] = true;
4483 } elseif (extension_loaded('xdebug')) {
4484 $warnings['xdebug_loaded'] = true;
4485 }
4486
4487 if (defined('PHP_WINDOWS_VERSION_BUILD')
4488 && (version_compare(PHP_VERSION, '7.2.23', '<')
4489 || (version_compare(PHP_VERSION, '7.3.0', '>=')
4490 && version_compare(PHP_VERSION, '7.3.10', '<')))) {
4491 $warnings['onedrive'] = PHP_VERSION;
4492 }
4493
4494 if (!empty($errors)) {
4495 foreach ($errors as $error => $current) {
4496 switch ($error) {
4497 case 'json':
4498 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
4499 $text .= "Install it or recompile php without --disable-json";
4500 break;
4501
4502 case 'phar':
4503 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
4504 $text .= "Install it or recompile php without --disable-phar";
4505 break;
4506
4507 case 'filter':
4508 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
4509 $text .= "Install it or recompile php without --disable-filter";
4510 break;
4511
4512 case 'hash':
4513 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
4514 $text .= "Install it or recompile php without --disable-hash";
4515 break;
4516
4517 case 'iconv_mbstring':
4518 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
4519 $text .= "Install either of them or recompile php without --disable-iconv";
4520 break;
4521
4522 case 'unicode':
4523 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
4524 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4525 $text .= "    detect_unicode = Off";
4526 $displayIniMessage = true;
4527 break;
4528
4529 case 'suhosin':
4530 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
4531 $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;
4532 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
4533 $displayIniMessage = true;
4534 break;
4535
4536 case 'php':
4537 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
4538 break;
4539
4540 case 'allow_url_fopen':
4541 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
4542 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4543 $text .= "    allow_url_fopen = On";
4544 $displayIniMessage = true;
4545 break;
4546
4547 case 'ioncube':
4548 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
4549 $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;
4550 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
4551 $displayIniMessage = true;
4552 break;
4553
4554 case 'openssl':
4555 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
4556 $text .= "If possible you should enable it or recompile php with --with-openssl";
4557 break;
4558 }
4559 $out($text, 'error');
4560 }
4561
4562 $output .= PHP_EOL;
4563 }
4564
4565 if (!empty($warnings)) {
4566 foreach ($warnings as $warning => $current) {
4567 switch ($warning) {
4568 case 'apc_cli':
4569 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
4570 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4571 $text .= "  apc.enable_cli = Off";
4572 $displayIniMessage = true;
4573 break;
4574
4575 case 'zlib':
4576 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
4577 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
4578 $displayIniMessage = true;
4579 break;
4580
4581 case 'sigchild':
4582 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
4583 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
4584 $text .= "  https://bugs.php.net/bug.php?id=22999";
4585 break;
4586
4587 case 'curlwrappers':
4588 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
4589 $text .= " Recompile it without this flag if possible";
4590 break;
4591
4592 case 'php':
4593 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
4594 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
4595 break;
4596
4597 case 'openssl_version':
4598
4599 $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
4600 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
4601
4602 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
4603 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
4604 break;
4605
4606 case 'xdebug_loaded':
4607 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
4608 $text .= " Disabling it when using Composer is recommended.";
4609 break;
4610
4611 case 'xdebug_profile':
4612 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
4613 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
4614 $text .= "  xdebug.profiler_enabled = 0";
4615 $displayIniMessage = true;
4616 break;
4617
4618 case 'onedrive':
4619 $text = "The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10.".PHP_EOL;
4620 $text .= "Upgrade your PHP ({$current}) to use this location with Composer.".PHP_EOL;
4621 break;
4622 }
4623 $out($text, 'comment');
4624 }
4625 }
4626
4627 if ($displayIniMessage) {
4628 $out($iniMessage, 'comment');
4629 }
4630
4631 return !$warnings && !$errors ? true : $output;
4632 }
4633
4634
4635
4636
4637
4638
4639
4640 private function checkConnectivity()
4641 {
4642 if (!ini_get('allow_url_fopen')) {
4643 $result = '<info>Skipped because allow_url_fopen is missing.</info>';
4644 return $result;
4645 }
4646
4647 return true;
4648 }
4649 }
4650 <?php
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662 namespace Composer\Command;
4663
4664 use Composer\Plugin\CommandEvent;
4665 use Composer\Plugin\PluginEvents;
4666 use Symfony\Component\Console\Input\InputInterface;
4667 use Symfony\Component\Console\Input\InputOption;
4668 use Symfony\Component\Console\Output\OutputInterface;
4669
4670
4671
4672
4673 class DumpAutoloadCommand extends BaseCommand
4674 {
4675 protected function configure()
4676 {
4677 $this
4678 ->setName('dump-autoload')
4679 ->setAliases(array('dumpautoload'))
4680 ->setDescription('Dumps the autoloader.')
4681 ->setDefinition(array(
4682 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4683 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4684 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4685 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4686 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4687 ))
4688 ->setHelp(
4689 <<<EOT
4690 <info>php composer.phar dump-autoload</info>
4691
4692 Read more at https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload-
4693 EOT
4694 )
4695 ;
4696 }
4697
4698 protected function execute(InputInterface $input, OutputInterface $output)
4699 {
4700 $composer = $this->getComposer();
4701
4702 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4703 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4704
4705 $installationManager = $composer->getInstallationManager();
4706 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4707 $package = $composer->getPackage();
4708 $config = $composer->getConfig();
4709
4710 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4711 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4712 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4713
4714 if ($authoritative) {
4715 $this->getIO()->write('<info>Generating optimized autoload files (authoritative)</info>');
4716 } elseif ($optimize) {
4717 $this->getIO()->write('<info>Generating optimized autoload files</info>');
4718 } else {
4719 $this->getIO()->write('<info>Generating autoload files</info>');
4720 }
4721
4722 $generator = $composer->getAutoloadGenerator();
4723 $generator->setDevMode(!$input->getOption('no-dev'));
4724 $generator->setClassMapAuthoritative($authoritative);
4725 $generator->setApcu($apcu);
4726 $generator->setRunScripts(!$input->getOption('no-scripts'));
4727 $numberOfClasses = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4728
4729 if ($authoritative) {
4730 $this->getIO()->write('<info>Generated optimized autoload files (authoritative) containing '. $numberOfClasses .' classes</info>');
4731 } elseif ($optimize) {
4732 $this->getIO()->write('<info>Generated optimized autoload files containing '. $numberOfClasses .' classes</info>');
4733 } else {
4734 $this->getIO()->write('<info>Generated autoload files</info>');
4735 }
4736
4737 return 0;
4738 }
4739 }
4740 <?php
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752 namespace Composer\Command;
4753
4754 use Symfony\Component\Console\Input\InputInterface;
4755 use Symfony\Component\Console\Input\InputOption;
4756 use Symfony\Component\Console\Output\OutputInterface;
4757 use Symfony\Component\Console\Input\InputArgument;
4758
4759
4760
4761
4762 class ExecCommand extends BaseCommand
4763 {
4764 protected function configure()
4765 {
4766 $this
4767 ->setName('exec')
4768 ->setDescription('Executes a vendored binary/script.')
4769 ->setDefinition(array(
4770 new InputOption('list', 'l', InputOption::VALUE_NONE),
4771 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4772 new InputArgument(
4773 'args',
4774 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4775 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4776 ),
4777 ))
4778 ->setHelp(
4779 <<<EOT
4780 Executes a vendored binary/script.
4781
4782 Read more at https://getcomposer.org/doc/03-cli.md#exec
4783 EOT
4784 )
4785 ;
4786 }
4787
4788 protected function execute(InputInterface $input, OutputInterface $output)
4789 {
4790 $composer = $this->getComposer();
4791 $binDir = $composer->getConfig()->get('bin-dir');
4792 if ($input->getOption('list') || !$input->getArgument('binary')) {
4793 $bins = glob($binDir . '/*');
4794 $bins = array_merge($bins, array_map(function ($e) {
4795 return "$e (local)";
4796 }, $composer->getPackage()->getBinaries()));
4797
4798 if (!$bins) {
4799 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4800 }
4801
4802 $this->getIO()->write(
4803 <<<EOT
4804 <comment>Available binaries:</comment>
4805 EOT
4806 );
4807
4808 foreach ($bins as $bin) {
4809
4810 if (isset($previousBin) && $bin === $previousBin.'.bat') {
4811 continue;
4812 }
4813
4814 $previousBin = $bin;
4815 $bin = basename($bin);
4816 $this->getIO()->write(
4817 <<<EOT
4818 <info>- $bin</info>
4819 EOT
4820 );
4821 }
4822
4823 return 0;
4824 }
4825
4826 $binary = $input->getArgument('binary');
4827
4828 $dispatcher = $composer->getEventDispatcher();
4829 $dispatcher->addListener('__exec_command', $binary);
4830 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4831 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4832 }
4833
4834
4835
4836
4837 if (getcwd() !== $this->getApplication()->getInitialWorkingDirectory()) {
4838 try {
4839 chdir($this->getApplication()->getInitialWorkingDirectory());
4840 } catch (\Exception $e) {
4841 throw new \RuntimeException('Could not switch back to working directory "'.$this->getApplication()->getInitialWorkingDirectory().'"', 0, $e);
4842 }
4843 }
4844
4845 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4846 }
4847 }
4848 <?php
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860 namespace Composer\Command;
4861
4862 use Composer\Package\CompletePackageInterface;
4863 use Composer\Package\AliasPackage;
4864 use Composer\Repository\CompositeRepository;
4865 use Symfony\Component\Console\Input\InputInterface;
4866 use Symfony\Component\Console\Input\InputOption;
4867 use Symfony\Component\Console\Output\OutputInterface;
4868
4869
4870
4871
4872
4873 class FundCommand extends BaseCommand
4874 {
4875 protected function configure()
4876 {
4877 $this->setName('fund')
4878 ->setDescription('Discover how to help fund the maintenance of your dependencies.')
4879 ;
4880 }
4881
4882 protected function execute(InputInterface $input, OutputInterface $output)
4883 {
4884 $composer = $this->getComposer();
4885
4886 $repo = $composer->getRepositoryManager()->getLocalRepository();
4887 $remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
4888 $fundings = array();
4889 foreach ($repo->getPackages() as $package) {
4890 if ($package instanceof AliasPackage) {
4891 continue;
4892 }
4893 $latest = $remoteRepos->findPackage($package->getName(), 'dev-master');
4894 if ($latest instanceof CompletePackageInterface && $latest->getFunding()) {
4895 $fundings = $this->insertFundingData($fundings, $latest);
4896 continue;
4897 }
4898 if ($package instanceof CompletePackageInterface && $package->getFunding()) {
4899 $fundings = $this->insertFundingData($fundings, $package);
4900 }
4901 }
4902
4903 ksort($fundings);
4904
4905 $io = $this->getIO();
4906
4907 if ($fundings) {
4908 $prev = null;
4909
4910 $io->write('The following packages were found in your dependencies which publish funding information:');
4911
4912 foreach ($fundings as $vendor => $links) {
4913 $io->write('');
4914 $io->write(sprintf("<comment>%s</comment>", $vendor));
4915 foreach ($links as $url => $packages) {
4916 $line = sprintf('  <info>%s</info>', implode(', ', $packages));
4917
4918 if ($prev !== $line) {
4919 $io->write($line);
4920 $prev = $line;
4921 }
4922
4923 $io->write(sprintf('    %s', $url));
4924 }
4925 }
4926
4927 $io->write("");
4928 $io->write("Please consider following these links and sponsoring the work of package authors!");
4929 $io->write("Thank you!");
4930 } else {
4931 $io->write("No funding links were found in your package dependencies. This doesn't mean they don't need your support!");
4932 }
4933
4934 return 0;
4935 }
4936
4937 private function insertFundingData(array $fundings, CompletePackageInterface $package)
4938 {
4939 foreach ($package->getFunding() as $fundingOption) {
4940 list($vendor, $packageName) = explode('/', $package->getPrettyName());
4941
4942 if (empty($fundingOption['url'])) {
4943 continue;
4944 }
4945 $url = $fundingOption['url'];
4946 if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && preg_match('{^https://github.com/([^/]+)$}', $url, $match)) {
4947 $url = 'https://github.com/sponsors/'.$match[1];
4948 }
4949 $fundings[$vendor][$url][] = $packageName;
4950 }
4951
4952 return $fundings;
4953 }
4954 }
4955 <?php
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967 namespace Composer\Command;
4968
4969 use Composer\Factory;
4970 use Composer\Util\Filesystem;
4971 use Symfony\Component\Console\Input\InputInterface;
4972 use Symfony\Component\Console\Input\InputArgument;
4973 use Symfony\Component\Console\Input\StringInput;
4974 use Symfony\Component\Console\Output\OutputInterface;
4975
4976
4977
4978
4979 class GlobalCommand extends BaseCommand
4980 {
4981 protected function configure()
4982 {
4983 $this
4984 ->setName('global')
4985 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4986 ->setDefinition(array(
4987 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4988 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4989 ))
4990 ->setHelp(
4991 <<<EOT
4992 Use this command as a wrapper to run other Composer commands
4993 within the global context of COMPOSER_HOME.
4994
4995 You can use this to install CLI utilities globally, all you need
4996 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4997
4998 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4999 and /home/<user>/.composer on unix systems.
5000
5001 If your system uses freedesktop.org standards, then it will first check
5002 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
5003
5004 Note: This path may vary depending on customizations to bin-dir in
5005 composer.json or the environmental variable COMPOSER_BIN_DIR.
5006
5007 Read more at https://getcomposer.org/doc/03-cli.md#global
5008 EOT
5009 )
5010 ;
5011 }
5012
5013 public function run(InputInterface $input, OutputInterface $output)
5014 {
5015
5016 $tokens = preg_split('{\s+}', $input->__toString());
5017 $args = array();
5018 foreach ($tokens as $token) {
5019 if ($token && $token[0] !== '-') {
5020 $args[] = $token;
5021 if (count($args) >= 2) {
5022 break;
5023 }
5024 }
5025 }
5026
5027
5028 if (count($args) < 2) {
5029 return parent::run($input, $output);
5030 }
5031
5032
5033 if (getenv('COMPOSER')) {
5034 putenv('COMPOSER');
5035 unset($_SERVER['COMPOSER']);
5036 }
5037
5038
5039 $config = Factory::createConfig();
5040 $home = $config->get('home');
5041
5042 if (!is_dir($home)) {
5043 $fs = new Filesystem();
5044 $fs->ensureDirectoryExists($home);
5045 if (!is_dir($home)) {
5046 throw new \RuntimeException('Could not create home directory');
5047 }
5048 }
5049
5050 try {
5051 chdir($home);
5052 } catch (\Exception $e) {
5053 throw new \RuntimeException('Could not switch to home directory "'.$home.'"', 0, $e);
5054 }
5055 $this->getIO()->writeError('<info>Changed current directory to '.$home.'</info>');
5056
5057
5058 $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
5059 $this->getApplication()->resetComposer();
5060
5061 return $this->getApplication()->run($input, $output);
5062 }
5063
5064
5065
5066
5067 public function isProxyCommand()
5068 {
5069 return true;
5070 }
5071 }
5072 <?php
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084 namespace Composer\Command;
5085
5086 use Composer\Package\CompletePackageInterface;
5087 use Composer\Repository\RepositoryInterface;
5088 use Composer\Repository\ArrayRepository;
5089 use Composer\Repository\RepositoryFactory;
5090 use Composer\Util\Platform;
5091 use Composer\Util\ProcessExecutor;
5092 use Symfony\Component\Console\Input\InputArgument;
5093 use Symfony\Component\Console\Input\InputOption;
5094 use Symfony\Component\Console\Input\InputInterface;
5095 use Symfony\Component\Console\Output\OutputInterface;
5096
5097
5098
5099
5100 class HomeCommand extends BaseCommand
5101 {
5102
5103
5104
5105 protected function configure()
5106 {
5107 $this
5108 ->setName('browse')
5109 ->setAliases(array('home'))
5110 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
5111 ->setDefinition(array(
5112 new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.'),
5113 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
5114 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
5115 ))
5116 ->setHelp(
5117 <<<EOT
5118 The home command opens or shows a package's repository URL or
5119 homepage in your default browser.
5120
5121 To open the homepage by default, use -H or --homepage.
5122 To show instead of open the repository or homepage URL, use -s or --show.
5123
5124 Read more at https://getcomposer.org/doc/03-cli.md#browse-home
5125 EOT
5126 );
5127 }
5128
5129
5130
5131
5132 protected function execute(InputInterface $input, OutputInterface $output)
5133 {
5134 $repos = $this->initializeRepos();
5135 $io = $this->getIO();
5136 $return = 0;
5137
5138 $packages = $input->getArgument('packages');
5139 if (!$packages) {
5140 $io->writeError('No package specified, opening homepage for the root package');
5141 $packages = array($this->getComposer()->getPackage()->getName());
5142 }
5143
5144 foreach ($packages as $packageName) {
5145 $handled = false;
5146 $packageExists = false;
5147 foreach ($repos as $repo) {
5148 foreach ($repo->findPackages($packageName) as $package) {
5149 $packageExists = true;
5150 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
5151 $handled = true;
5152 break 2;
5153 }
5154 }
5155 }
5156
5157 if (!$packageExists) {
5158 $return = 1;
5159 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
5160 }
5161
5162 if (!$handled) {
5163 $return = 1;
5164 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
5165 }
5166 }
5167
5168 return $return;
5169 }
5170
5171 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
5172 {
5173 $support = $package->getSupport();
5174 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
5175 if (!$url || $showHomepage) {
5176 $url = $package->getHomepage();
5177 }
5178
5179 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
5180 return false;
5181 }
5182
5183 if ($showOnly) {
5184 $this->getIO()->write(sprintf('<info>%s</info>', $url));
5185 } else {
5186 $this->openBrowser($url);
5187 }
5188
5189 return true;
5190 }
5191
5192
5193
5194
5195
5196
5197 private function openBrowser($url)
5198 {
5199 $url = ProcessExecutor::escape($url);
5200
5201 $process = new ProcessExecutor($this->getIO());
5202 if (Platform::isWindows()) {
5203 return $process->execute('start "web" explorer ' . $url, $output);
5204 }
5205
5206 $linux = $process->execute('which xdg-open', $output);
5207 $osx = $process->execute('which open', $output);
5208
5209 if (0 === $linux) {
5210 $process->execute('xdg-open ' . $url, $output);
5211 } elseif (0 === $osx) {
5212 $process->execute('open ' . $url, $output);
5213 } else {
5214 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
5215 }
5216 }
5217
5218
5219
5220
5221
5222
5223
5224
5225 private function initializeRepos()
5226 {
5227 $composer = $this->getComposer(false);
5228
5229 if ($composer) {
5230 return array_merge(
5231 array(new ArrayRepository(array($composer->getPackage()))), 
5232 array($composer->getRepositoryManager()->getLocalRepository()), 
5233 $composer->getRepositoryManager()->getRepositories() 
5234 );
5235 }
5236
5237 return RepositoryFactory::defaultRepos($this->getIO());
5238 }
5239 }
5240 <?php
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252 namespace Composer\Command;
5253
5254 use Composer\DependencyResolver\Pool;
5255 use Composer\Factory;
5256 use Composer\Json\JsonFile;
5257 use Composer\Package\BasePackage;
5258 use Composer\Package\Package;
5259 use Composer\Package\Version\VersionParser;
5260 use Composer\Package\Version\VersionSelector;
5261 use Composer\Repository\CompositeRepository;
5262 use Composer\Repository\PlatformRepository;
5263 use Composer\Repository\RepositoryFactory;
5264 use Composer\Util\ProcessExecutor;
5265 use Symfony\Component\Console\Input\ArrayInput;
5266 use Symfony\Component\Console\Input\InputInterface;
5267 use Symfony\Component\Console\Input\InputOption;
5268 use Symfony\Component\Console\Output\OutputInterface;
5269 use Symfony\Component\Process\ExecutableFinder;
5270 use Symfony\Component\Process\Process;
5271
5272
5273
5274
5275
5276 class InitCommand extends BaseCommand
5277 {
5278
5279 protected $repos;
5280
5281
5282 private $gitConfig;
5283
5284
5285 private $pools;
5286
5287
5288
5289
5290 protected function configure()
5291 {
5292 $this
5293 ->setName('init')
5294 ->setDescription('Creates a basic composer.json file in current directory.')
5295 ->setDefinition(array(
5296 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
5297 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
5298 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
5299
5300 new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
5301 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
5302 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"'),
5303 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"'),
5304 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
5305 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
5306 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
5307 ))
5308 ->setHelp(
5309 <<<EOT
5310 The <info>init</info> command creates a basic composer.json file
5311 in the current directory.
5312
5313 <info>php composer.phar init</info>
5314
5315 Read more at https://getcomposer.org/doc/03-cli.md#init
5316 EOT
5317 )
5318 ;
5319 }
5320
5321
5322
5323
5324 protected function execute(InputInterface $input, OutputInterface $output)
5325 {
5326 $io = $this->getIO();
5327
5328 $allowList = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
5329 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($allowList)));
5330
5331 if (isset($options['author'])) {
5332 $options['authors'] = $this->formatAuthors($options['author']);
5333 unset($options['author']);
5334 }
5335
5336 $repositories = $input->getOption('repository');
5337 if ($repositories) {
5338 $config = Factory::createConfig($io);
5339 foreach ($repositories as $repo) {
5340 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
5341 }
5342 }
5343
5344 if (isset($options['stability'])) {
5345 $options['minimum-stability'] = $options['stability'];
5346 unset($options['stability']);
5347 }
5348
5349 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
5350 if (array() === $options['require']) {
5351 $options['require'] = new \stdClass;
5352 }
5353
5354 if (isset($options['require-dev'])) {
5355 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
5356 if (array() === $options['require-dev']) {
5357 $options['require-dev'] = new \stdClass;
5358 }
5359 }
5360
5361 $file = new JsonFile(Factory::getComposerFile());
5362 $json = $file->encode($options);
5363
5364 if ($input->isInteractive()) {
5365 $io->writeError(array('', $json, ''));
5366 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
5367 $io->writeError('<error>Command aborted</error>');
5368
5369 return 1;
5370 }
5371 }
5372
5373 $file->write($options);
5374
5375 if ($input->isInteractive() && is_dir('.git')) {
5376 $ignoreFile = realpath('.gitignore');
5377
5378 if (false === $ignoreFile) {
5379 $ignoreFile = realpath('.') . '/.gitignore';
5380 }
5381
5382 if (!$this->hasVendorIgnore($ignoreFile)) {
5383 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
5384
5385 if ($io->askConfirmation($question, true)) {
5386 $this->addVendorIgnore($ignoreFile);
5387 }
5388 }
5389 }
5390
5391 $question = 'Would you like to install dependencies now [<comment>yes</comment>]? ';
5392 if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question, true)) {
5393 $this->installDependencies($output);
5394 }
5395
5396 return 0;
5397 }
5398
5399
5400
5401
5402 protected function interact(InputInterface $input, OutputInterface $output)
5403 {
5404 $git = $this->getGitConfig();
5405 $io = $this->getIO();
5406 $formatter = $this->getHelperSet()->get('formatter');
5407
5408
5409 $repositories = $input->getOption('repository');
5410 if ($repositories) {
5411 $config = Factory::createConfig($io);
5412 $repos = array(new PlatformRepository);
5413 $createDefaultPackagistRepo = true;
5414 foreach ($repositories as $repo) {
5415 $repoConfig = RepositoryFactory::configFromString($io, $config, $repo);
5416 if (
5417 (isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
5418 || (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
5419 ) {
5420 $createDefaultPackagistRepo = false;
5421 continue;
5422 }
5423 $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig);
5424 }
5425
5426 if ($createDefaultPackagistRepo) {
5427 $repos[] = RepositoryFactory::createRepo($io, $config, array(
5428 'type' => 'composer',
5429 'url' => 'https://repo.packagist.org',
5430 ));
5431 }
5432
5433 $this->repos = new CompositeRepository($repos);
5434 unset($repos, $config, $repositories);
5435 }
5436
5437 $io->writeError(array(
5438 '',
5439 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
5440 '',
5441 ));
5442
5443
5444 $io->writeError(array(
5445 '',
5446 'This command will guide you through creating your composer.json config.',
5447 '',
5448 ));
5449
5450 $cwd = realpath(".");
5451
5452 if (!$name = $input->getOption('name')) {
5453 $name = basename($cwd);
5454 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
5455 $name = strtolower($name);
5456 if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
5457 $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
5458 } elseif (isset($git['github.user'])) {
5459 $name = $git['github.user'] . '/' . $name;
5460 } elseif (!empty($_SERVER['USERNAME'])) {
5461 $name = $_SERVER['USERNAME'] . '/' . $name;
5462 } elseif (!empty($_SERVER['USER'])) {
5463 $name = $_SERVER['USER'] . '/' . $name;
5464 } elseif (get_current_user()) {
5465 $name = get_current_user() . '/' . $name;
5466 } else {
5467
5468 $name .= '/' . $name;
5469 }
5470 $name = strtolower($name);
5471 } else {
5472 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $name)) {
5473 throw new \InvalidArgumentException(
5474 '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_.-]+'
5475 );
5476 }
5477 }
5478
5479 $name = $io->askAndValidate(
5480 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
5481 function ($value) use ($name) {
5482 if (null === $value) {
5483 return $name;
5484 }
5485
5486 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $value)) {
5487 throw new \InvalidArgumentException(
5488 '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_.-]+'
5489 );
5490 }
5491
5492 return $value;
5493 },
5494 null,
5495 $name
5496 );
5497 $input->setOption('name', $name);
5498
5499 $description = $input->getOption('description') ?: false;
5500 $description = $io->ask(
5501 'Description [<comment>'.$description.'</comment>]: ',
5502 $description
5503 );
5504 $input->setOption('description', $description);
5505
5506 if (null === $author = $input->getOption('author')) {
5507 if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
5508 $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
5509 } elseif (isset($git['user.name'])) {
5510 $author_name = $git['user.name'];
5511 }
5512
5513 if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
5514 $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
5515 } elseif (isset($git['user.email'])) {
5516 $author_email = $git['user.email'];
5517 }
5518
5519 if (isset($author_name) && isset($author_email)) {
5520 $author = sprintf('%s <%s>', $author_name, $author_email);
5521 }
5522 }
5523
5524 $self = $this;
5525 $author = $io->askAndValidate(
5526 'Author [<comment>'.$author.'</comment>, n to skip]: ',
5527 function ($value) use ($self, $author) {
5528 if ($value === 'n' || $value === 'no') {
5529 return;
5530 }
5531 $value = $value ?: $author;
5532 $author = $self->parseAuthorString($value);
5533
5534 return sprintf('%s <%s>', $author['name'], $author['email']);
5535 },
5536 null,
5537 $author
5538 );
5539 $input->setOption('author', $author);
5540
5541 $minimumStability = $input->getOption('stability') ?: null;
5542 $minimumStability = $io->askAndValidate(
5543 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
5544 function ($value) use ($minimumStability) {
5545 if (null === $value) {
5546 return $minimumStability;
5547 }
5548
5549 if (!isset(BasePackage::$stabilities[$value])) {
5550 throw new \InvalidArgumentException(
5551 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
5552 implode(', ', array_keys(BasePackage::$stabilities))
5553 );
5554 }
5555
5556 return $value;
5557 },
5558 null,
5559 $minimumStability
5560 );
5561 $input->setOption('stability', $minimumStability);
5562
5563 $type = $input->getOption('type') ?: false;
5564 $type = $io->ask(
5565 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
5566 $type
5567 );
5568 $input->setOption('type', $type);
5569
5570 if (null === $license = $input->getOption('license')) {
5571 if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
5572 $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
5573 }
5574 }
5575
5576 $license = $io->ask(
5577 'License [<comment>'.$license.'</comment>]: ',
5578 $license
5579 );
5580 $input->setOption('license', $license);
5581
5582 $io->writeError(array('', 'Define your dependencies.', ''));
5583
5584
5585 $repos = $this->getRepos();
5586 $preferredStability = $minimumStability ?: 'stable';
5587 $phpVersion = $repos->findPackage('php', '*')->getPrettyVersion();
5588
5589 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
5590 $require = $input->getOption('require');
5591 $requirements = array();
5592 if ($require || $io->askConfirmation($question, true)) {
5593 $requirements = $this->determineRequirements($input, $output, $require, $phpVersion, $preferredStability);
5594 }
5595 $input->setOption('require', $requirements);
5596
5597 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
5598 $requireDev = $input->getOption('require-dev');
5599 $devRequirements = array();
5600 if ($requireDev || $io->askConfirmation($question, true)) {
5601 $devRequirements = $this->determineRequirements($input, $output, $requireDev, $phpVersion, $preferredStability);
5602 }
5603 $input->setOption('require-dev', $devRequirements);
5604 }
5605
5606
5607
5608
5609
5610
5611 public function parseAuthorString($author)
5612 {
5613 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
5614 if ($this->isValidEmail($match['email'])) {
5615 return array(
5616 'name' => trim($match['name']),
5617 'email' => $match['email'],
5618 );
5619 }
5620 }
5621
5622 throw new \InvalidArgumentException(
5623 'Invalid author string.  Must be in the format: '.
5624 'John Smith <john@example.com>'
5625 );
5626 }
5627
5628 protected function findPackages($name)
5629 {
5630 return $this->getRepos()->search($name);
5631 }
5632
5633 protected function getRepos()
5634 {
5635 if (!$this->repos) {
5636 $this->repos = new CompositeRepository(array_merge(
5637 array(new PlatformRepository),
5638 RepositoryFactory::defaultRepos($this->getIO())
5639 ));
5640 }
5641
5642 return $this->repos;
5643 }
5644
5645 final protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true, $fixed = false)
5646 {
5647 if ($requires) {
5648 $requires = $this->normalizeRequirements($requires);
5649 $result = array();
5650 $io = $this->getIO();
5651
5652 foreach ($requires as $requirement) {
5653 if (!isset($requirement['version'])) {
5654
5655 list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, null, null, $fixed);
5656 $requirement['version'] = $version;
5657
5658
5659 $requirement['name'] = $name;
5660
5661 $io->writeError(sprintf(
5662 'Using version <info>%s</info> for <info>%s</info>',
5663 $requirement['version'],
5664 $requirement['name']
5665 ));
5666 } else {
5667
5668 list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev', $fixed);
5669
5670
5671 $requirement['name'] = $name;
5672 }
5673
5674 $result[] = $requirement['name'] . ' ' . $requirement['version'];
5675 }
5676
5677 return $result;
5678 }
5679
5680 $versionParser = new VersionParser();
5681
5682
5683 $composer = $this->getComposer(false);
5684 $installedRepo = $composer ? $composer->getRepositoryManager()->getLocalRepository() : null;
5685 $existingPackages = array();
5686 if ($installedRepo) {
5687 foreach ($installedRepo->getPackages() as $package) {
5688 $existingPackages[] = $package->getName();
5689 }
5690 }
5691 unset($composer, $installedRepo);
5692
5693 $io = $this->getIO();
5694 while (null !== $package = $io->ask('Search for a package: ')) {
5695 $matches = $this->findPackages($package);
5696
5697 if (count($matches)) {
5698
5699 foreach ($matches as $position => $foundPackage) {
5700 if (in_array($foundPackage['name'], $existingPackages, true)) {
5701 unset($matches[$position]);
5702 }
5703 }
5704 $matches = array_values($matches);
5705
5706 $exactMatch = null;
5707 $choices = array();
5708 foreach ($matches as $position => $foundPackage) {
5709 $abandoned = '';
5710 if (isset($foundPackage['abandoned'])) {
5711 if (is_string($foundPackage['abandoned'])) {
5712 $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
5713 } else {
5714 $replacement = 'No replacement was suggested';
5715 }
5716 $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
5717 }
5718
5719 $choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
5720 if ($foundPackage['name'] === $package) {
5721 $exactMatch = true;
5722 break;
5723 }
5724 }
5725
5726
5727 if (!$exactMatch) {
5728 $io->writeError(array(
5729 '',
5730 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
5731 '',
5732 ));
5733
5734 $io->writeError($choices);
5735 $io->writeError('');
5736
5737 $validator = function ($selection) use ($matches, $versionParser) {
5738 if ('' === $selection) {
5739 return false;
5740 }
5741
5742 if (is_numeric($selection) && isset($matches[(int) $selection])) {
5743 $package = $matches[(int) $selection];
5744
5745 return $package['name'];
5746 }
5747
5748 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
5749 if (isset($packageMatches['version'])) {
5750
5751
5752
5753 $versionParser->parseConstraints($packageMatches['version']);
5754
5755 return $packageMatches['name'].' '.$packageMatches['version'];
5756 }
5757
5758
5759 return $packageMatches['name'];
5760 }
5761
5762 throw new \Exception('Not a valid selection');
5763 };
5764
5765 $package = $io->askAndValidate(
5766 'Enter package # to add, or the complete package name if it is not listed: ',
5767 $validator,
5768 3,
5769 false
5770 );
5771 }
5772
5773
5774 if (false !== $package && false === strpos($package, ' ')) {
5775 $validator = function ($input) {
5776 $input = trim($input);
5777
5778 return $input ?: false;
5779 };
5780
5781 $constraint = $io->askAndValidate(
5782 'Enter the version constraint to require (or leave blank to use the latest version): ',
5783 $validator,
5784 3,
5785 false
5786 );
5787
5788 if (false === $constraint) {
5789 list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
5790
5791 $io->writeError(sprintf(
5792 'Using version <info>%s</info> for <info>%s</info>',
5793 $constraint,
5794 $package
5795 ));
5796 }
5797
5798 $package .= ' '.$constraint;
5799 }
5800
5801 if (false !== $package) {
5802 $requires[] = $package;
5803 $existingPackages[] = substr($package, 0, strpos($package, ' '));
5804 }
5805 }
5806 }
5807
5808 return $requires;
5809 }
5810
5811 protected function formatAuthors($author)
5812 {
5813 return array($this->parseAuthorString($author));
5814 }
5815
5816 protected function formatRequirements(array $requirements)
5817 {
5818 $requires = array();
5819 $requirements = $this->normalizeRequirements($requirements);
5820 foreach ($requirements as $requirement) {
5821 $requires[$requirement['name']] = $requirement['version'];
5822 }
5823
5824 return $requires;
5825 }
5826
5827 protected function getGitConfig()
5828 {
5829 if (null !== $this->gitConfig) {
5830 return $this->gitConfig;
5831 }
5832
5833 $finder = new ExecutableFinder();
5834 $gitBin = $finder->find('git');
5835
5836
5837 if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
5838 $cmd = new Process(array($gitBin, 'config', '-l'));
5839 } else {
5840 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
5841 }
5842 $cmd->run();
5843
5844 if ($cmd->isSuccessful()) {
5845 $this->gitConfig = array();
5846 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
5847 foreach ($matches as $match) {
5848 $this->gitConfig[$match[1]] = $match[2];
5849 }
5850
5851 return $this->gitConfig;
5852 }
5853
5854 return $this->gitConfig = array();
5855 }
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
5874 {
5875 if (!file_exists($ignoreFile)) {
5876 return false;
5877 }
5878
5879 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
5880
5881 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
5882 foreach ($lines as $line) {
5883 if (preg_match($pattern, $line)) {
5884 return true;
5885 }
5886 }
5887
5888 return false;
5889 }
5890
5891 protected function normalizeRequirements(array $requirements)
5892 {
5893 $parser = new VersionParser();
5894
5895 return $parser->parseNameVersionPairs($requirements);
5896 }
5897
5898 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
5899 {
5900 $contents = "";
5901 if (file_exists($ignoreFile)) {
5902 $contents = file_get_contents($ignoreFile);
5903
5904 if ("\n" !== substr($contents, 0, -1)) {
5905 $contents .= "\n";
5906 }
5907 }
5908
5909 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5910 }
5911
5912 protected function isValidEmail($email)
5913 {
5914
5915 if (!function_exists('filter_var')) {
5916 return true;
5917 }
5918
5919
5920 if (PHP_VERSION_ID < 50303) {
5921 return true;
5922 }
5923
5924 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5925 }
5926
5927 private function getPool(InputInterface $input, $minimumStability = null)
5928 {
5929 $key = $minimumStability ?: 'default';
5930
5931 if (!isset($this->pools[$key])) {
5932 $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5933 $pool->addRepository($this->getRepos());
5934 }
5935
5936 return $this->pools[$key];
5937 }
5938
5939 private function getMinimumStability(InputInterface $input)
5940 {
5941 if ($input->hasOption('stability')) {
5942 return VersionParser::normalizeStability($input->getOption('stability') ?: 'stable');
5943 }
5944
5945 $file = Factory::getComposerFile();
5946 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5947 if (!empty($composer['minimum-stability'])) {
5948 return VersionParser::normalizeStability($composer['minimum-stability']);
5949 }
5950 }
5951
5952 return 'stable';
5953 }
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970 private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null, $fixed = null)
5971 {
5972
5973 $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5974 $ignorePlatformReqs = $input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs');
5975
5976
5977 if ($ignorePlatformReqs) {
5978 $phpVersion = null;
5979 }
5980
5981 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5982
5983 if (!$package) {
5984
5985
5986 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
5987 return array($name, $requiredVersion ?: '*');
5988 }
5989
5990
5991 if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
5992 throw new \InvalidArgumentException(sprintf(
5993 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)',
5994 $name,
5995 $requiredVersion,
5996 $phpVersion
5997 ));
5998 }
5999
6000 if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
6001 throw new \InvalidArgumentException(sprintf(
6002 'Could not find package %s in a version matching %s',
6003 $name,
6004 $requiredVersion
6005 ));
6006 }
6007
6008 if ($phpVersion && $versionSelector->findBestCandidate($name)) {
6009 throw new \InvalidArgumentException(sprintf(
6010 'Could not find package %s in any version matching your PHP version (%s)',
6011 $name,
6012 $phpVersion
6013 ));
6014 }
6015
6016
6017 $similar = $this->findSimilar($name);
6018 if ($similar) {
6019
6020 if ($requiredVersion === null && in_array($name, $similar, true)) {
6021 throw new \InvalidArgumentException(sprintf(
6022 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
6023 $name,
6024 $this->getMinimumStability($input)
6025 ));
6026 }
6027
6028 throw new \InvalidArgumentException(sprintf(
6029 "Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s",
6030 $name,
6031 implode("\n    ", $similar)
6032 ));
6033 }
6034
6035 throw new \InvalidArgumentException(sprintf(
6036 'Could not find a matching version of package %s. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (%s).',
6037 $name,
6038 $this->getMinimumStability($input)
6039 ));
6040 }
6041
6042 return array(
6043 $package->getPrettyName(),
6044 $fixed ? $package->getPrettyVersion() : $versionSelector->findRecommendedRequireVersion($package),
6045 );
6046 }
6047
6048 private function findSimilar($package)
6049 {
6050 try {
6051 $results = $this->repos->search($package);
6052 } catch (\Exception $e) {
6053
6054 return array();
6055 }
6056 $similarPackages = array();
6057
6058 $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
6059
6060 foreach ($results as $result) {
6061 if ($installedRepo->findPackage($result['name'], '*')) {
6062
6063 continue;
6064 }
6065 $similarPackages[$result['name']] = levenshtein($package, $result['name']);
6066 }
6067 asort($similarPackages);
6068
6069 return array_keys(array_slice($similarPackages, 0, 5));
6070 }
6071
6072 private function installDependencies($output)
6073 {
6074 try {
6075 $installCommand = $this->getApplication()->find('install');
6076 $installCommand->run(new ArrayInput(array()), $output);
6077 } catch (\Exception $e) {
6078 $this->getIO()->writeError('Could not install dependencies. Run `composer install` to see more information.');
6079 }
6080
6081 }
6082
6083 private function hasDependencies($options)
6084 {
6085 $requires = (array) $options['require'];
6086 $devRequires = isset($options['require-dev']) ? (array) $options['require-dev'] : array();
6087
6088 return !empty($requires) || !empty($devRequires);
6089 }
6090 }
6091 <?php
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103 namespace Composer\Command;
6104
6105 use Composer\Composer;
6106 use Composer\Installer;
6107 use Composer\Plugin\CommandEvent;
6108 use Composer\Plugin\PluginEvents;
6109 use Symfony\Component\Console\Input\InputInterface;
6110 use Symfony\Component\Console\Input\InputOption;
6111 use Symfony\Component\Console\Input\InputArgument;
6112 use Symfony\Component\Console\Output\OutputInterface;
6113
6114
6115
6116
6117
6118
6119
6120 class InstallCommand extends BaseCommand
6121 {
6122 protected function configure()
6123 {
6124 $this
6125 ->setName('install')
6126 ->setAliases(array('i'))
6127 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
6128 ->setDefinition(array(
6129 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
6130 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
6131 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
6132 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
6133 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
6134 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
6135 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
6136 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6137 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6138 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
6139 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
6140 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6141 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6142 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6143 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6144 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
6145 ))
6146 ->setHelp(
6147 <<<EOT
6148 The <info>install</info> command reads the composer.lock file from
6149 the current directory, processes it, and downloads and installs all the
6150 libraries and dependencies outlined in that file. If the file does not
6151 exist it will look for composer.json and do the same.
6152
6153 <info>php composer.phar install</info>
6154
6155 Read more at https://getcomposer.org/doc/03-cli.md#install-i
6156 EOT
6157 )
6158 ;
6159 }
6160
6161 protected function execute(InputInterface $input, OutputInterface $output)
6162 {
6163 $io = $this->getIO();
6164 if ($args = $input->getArgument('packages')) {
6165 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
6166
6167 return 1;
6168 }
6169
6170 if ($input->getOption('no-custom-installers')) {
6171 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
6172 $input->setOption('no-plugins', true);
6173 }
6174
6175 if ($input->getOption('dev')) {
6176 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
6177 }
6178
6179 $io->writeError('<warning>You are using Composer 1 which is deprecated. You should upgrade to Composer 2, see https://blog.packagist.com/deprecating-composer-1-support/</warning>');
6180
6181 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6182 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6183
6184 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
6185 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6186
6187 $install = Installer::create($io, $composer);
6188
6189 $config = $composer->getConfig();
6190 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
6191
6192 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
6193 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
6194 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
6195
6196 $install
6197 ->setDryRun($input->getOption('dry-run'))
6198 ->setVerbose($input->getOption('verbose'))
6199 ->setPreferSource($preferSource)
6200 ->setPreferDist($preferDist)
6201 ->setDevMode(!$input->getOption('no-dev'))
6202 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
6203 ->setRunScripts(!$input->getOption('no-scripts'))
6204 ->setSkipSuggest($input->getOption('no-suggest'))
6205 ->setOptimizeAutoloader($optimize)
6206 ->setClassMapAuthoritative($authoritative)
6207 ->setApcuAutoloader($apcu)
6208 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6209 ;
6210
6211 if ($input->getOption('no-plugins')) {
6212 $install->disablePlugins();
6213 }
6214
6215 return $install->run();
6216 }
6217 }
6218 <?php
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230 namespace Composer\Command;
6231
6232 use Composer\Json\JsonFile;
6233 use Composer\Plugin\CommandEvent;
6234 use Composer\Plugin\PluginEvents;
6235 use Composer\Package\PackageInterface;
6236 use Composer\Repository\RepositoryInterface;
6237 use Symfony\Component\Console\Helper\Table;
6238 use Symfony\Component\Console\Input\InputInterface;
6239 use Symfony\Component\Console\Input\InputOption;
6240 use Symfony\Component\Console\Output\OutputInterface;
6241
6242
6243
6244
6245 class LicensesCommand extends BaseCommand
6246 {
6247 protected function configure()
6248 {
6249 $this
6250 ->setName('licenses')
6251 ->setDescription('Shows information about licenses of dependencies.')
6252 ->setDefinition(array(
6253 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6254 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
6255 ))
6256 ->setHelp(
6257 <<<EOT
6258 The license command displays detailed information about the licenses of
6259 the installed dependencies.
6260
6261 Read more at https://getcomposer.org/doc/03-cli.md#licenses
6262 EOT
6263 )
6264 ;
6265 }
6266
6267 protected function execute(InputInterface $input, OutputInterface $output)
6268 {
6269 $composer = $this->getComposer();
6270
6271 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
6272 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6273
6274 $root = $composer->getPackage();
6275 $repo = $composer->getRepositoryManager()->getLocalRepository();
6276
6277 if ($input->getOption('no-dev')) {
6278 $packages = $this->filterRequiredPackages($repo, $root);
6279 } else {
6280 $packages = $this->appendPackages($repo->getPackages(), array());
6281 }
6282
6283 ksort($packages);
6284 $io = $this->getIO();
6285
6286 switch ($format = $input->getOption('format')) {
6287 case 'text':
6288 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
6289 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
6290 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
6291 $io->write('Dependencies:');
6292 $io->write('');
6293
6294 $table = new Table($output);
6295 $table->setStyle('compact');
6296 $tableStyle = $table->getStyle();
6297 if (method_exists($tableStyle, 'setVerticalBorderChars')) {
6298 $tableStyle->setVerticalBorderChars('');
6299 } else {
6300 $tableStyle->setVerticalBorderChar('');
6301 }
6302 $tableStyle->setCellRowContentFormat('%s  ');
6303 $table->setHeaders(array('Name', 'Version', 'License'));
6304 foreach ($packages as $package) {
6305 $table->addRow(array(
6306 $package->getPrettyName(),
6307 $package->getFullPrettyVersion(),
6308 implode(', ', $package->getLicense()) ?: 'none',
6309 ));
6310 }
6311 $table->render();
6312 break;
6313
6314 case 'json':
6315 $dependencies = array();
6316 foreach ($packages as $package) {
6317 $dependencies[$package->getPrettyName()] = array(
6318 'version' => $package->getFullPrettyVersion(),
6319 'license' => $package->getLicense(),
6320 );
6321 }
6322
6323 $io->write(JsonFile::encode(array(
6324 'name' => $root->getPrettyName(),
6325 'version' => $root->getFullPrettyVersion(),
6326 'license' => $root->getLicense(),
6327 'dependencies' => $dependencies,
6328 )));
6329 break;
6330
6331 default:
6332 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
6333 }
6334
6335 return 0;
6336 }
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
6347 {
6348 $requires = array_keys($package->getRequires());
6349
6350 $packageListNames = array_keys($bucket);
6351 $packages = array_filter(
6352 $repo->getPackages(),
6353 function ($package) use ($requires, $packageListNames) {
6354 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
6355 }
6356 );
6357
6358 $bucket = $this->appendPackages($packages, $bucket);
6359
6360 foreach ($packages as $package) {
6361 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
6362 }
6363
6364 return $bucket;
6365 }
6366
6367
6368
6369
6370
6371
6372
6373
6374 public function appendPackages(array $packages, array $bucket)
6375 {
6376 foreach ($packages as $package) {
6377 $bucket[$package->getName()] = $package;
6378 }
6379
6380 return $bucket;
6381 }
6382 }
6383 <?php
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395 namespace Composer\Command;
6396
6397 use Symfony\Component\Console\Input\InputInterface;
6398 use Symfony\Component\Console\Input\InputArgument;
6399 use Symfony\Component\Console\Input\ArrayInput;
6400 use Symfony\Component\Console\Input\InputOption;
6401 use Symfony\Component\Console\Output\OutputInterface;
6402
6403
6404
6405
6406 class OutdatedCommand extends ShowCommand
6407 {
6408 protected function configure()
6409 {
6410 $this
6411 ->setName('outdated')
6412 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
6413 ->setDefinition(array(
6414 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
6415 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
6416 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
6417 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
6418 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
6419 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
6420 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6421 new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.'),
6422 ))
6423 ->setHelp(
6424 <<<EOT
6425 The outdated command is just a proxy for `composer show -l`
6426
6427 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
6428
6429 - <info>green</info> (=): Dependency is in the latest version and is up to date.
6430 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
6431   compatibility breaks according to semver, so upgrade when you can but it
6432   may involve work.
6433 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
6434
6435 Read more at https://getcomposer.org/doc/03-cli.md#outdated
6436 EOT
6437 )
6438 ;
6439 }
6440
6441 protected function execute(InputInterface $input, OutputInterface $output)
6442 {
6443 $args = array(
6444 'command' => 'show',
6445 '--latest' => true,
6446 );
6447 if (!$input->getOption('all')) {
6448 $args['--outdated'] = true;
6449 }
6450 if ($input->getOption('direct')) {
6451 $args['--direct'] = true;
6452 }
6453 if ($input->getArgument('package')) {
6454 $args['package'] = $input->getArgument('package');
6455 }
6456 if ($input->getOption('strict')) {
6457 $args['--strict'] = true;
6458 }
6459 if ($input->getOption('minor-only')) {
6460 $args['--minor-only'] = true;
6461 }
6462 $args['--format'] = $input->getOption('format');
6463 $args['--ignore'] = $input->getOption('ignore');
6464
6465 $input = new ArrayInput($args);
6466
6467 return $this->getApplication()->run($input, $output);
6468 }
6469
6470
6471
6472
6473 public function isProxyCommand()
6474 {
6475 return true;
6476 }
6477 }
6478 <?php
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490 namespace Composer\Command;
6491
6492 use Symfony\Component\Console\Input\InputInterface;
6493 use Symfony\Component\Console\Output\OutputInterface;
6494
6495
6496
6497
6498 class ProhibitsCommand extends BaseDependencyCommand
6499 {
6500
6501
6502
6503 protected function configure()
6504 {
6505 parent::configure();
6506
6507 $this
6508 ->setName('prohibits')
6509 ->setAliases(array('why-not'))
6510 ->setDescription('Shows which packages prevent the given package from being installed.')
6511 ->setHelp(
6512 <<<EOT
6513 Displays detailed information about why a package cannot be installed.
6514
6515 <info>php composer.phar prohibits composer/composer</info>
6516
6517 Read more at https://getcomposer.org/doc/03-cli.md#prohibits-why-not-
6518 EOT
6519 )
6520 ;
6521 }
6522
6523
6524
6525
6526
6527
6528
6529
6530 protected function execute(InputInterface $input, OutputInterface $output)
6531 {
6532 return parent::doExecute($input, $output, true);
6533 }
6534 }
6535 <?php
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547 namespace Composer\Command;
6548
6549 use Composer\Config\JsonConfigSource;
6550 use Composer\Installer;
6551 use Composer\Plugin\CommandEvent;
6552 use Composer\Plugin\PluginEvents;
6553 use Composer\Json\JsonFile;
6554 use Composer\Factory;
6555 use Symfony\Component\Console\Input\InputInterface;
6556 use Symfony\Component\Console\Input\InputOption;
6557 use Symfony\Component\Console\Input\InputArgument;
6558 use Symfony\Component\Console\Output\OutputInterface;
6559 use Composer\Package\BasePackage;
6560
6561
6562
6563
6564
6565 class RemoveCommand extends BaseCommand
6566 {
6567 protected function configure()
6568 {
6569 $this
6570 ->setName('remove')
6571 ->setDescription('Removes a package from the require or require-dev.')
6572 ->setDefinition(array(
6573 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
6574 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
6575 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6576 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6577 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6578 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6579 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
6580 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
6581 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6582 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6583 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6584 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6585 ))
6586 ->setHelp(
6587 <<<EOT
6588 The <info>remove</info> command removes a package from the current
6589 list of installed packages
6590
6591 <info>php composer.phar remove</info>
6592
6593 Read more at https://getcomposer.org/doc/03-cli.md#remove
6594 EOT
6595 )
6596 ;
6597 }
6598
6599 protected function execute(InputInterface $input, OutputInterface $output)
6600 {
6601 $packages = $input->getArgument('packages');
6602 $packages = array_map('strtolower', $packages);
6603
6604 $file = Factory::getComposerFile();
6605
6606 $jsonFile = new JsonFile($file);
6607 $composer = $jsonFile->read();
6608 $composerBackup = file_get_contents($jsonFile->getPath());
6609
6610 $json = new JsonConfigSource($jsonFile);
6611
6612 $type = $input->getOption('dev') ? 'require-dev' : 'require';
6613 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
6614 $io = $this->getIO();
6615
6616 if ($input->getOption('update-with-dependencies')) {
6617 $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>');
6618 }
6619
6620
6621 foreach (array('require', 'require-dev') as $linkType) {
6622 if (isset($composer[$linkType])) {
6623 foreach ($composer[$linkType] as $name => $version) {
6624 $composer[$linkType][strtolower($name)] = $name;
6625 }
6626 }
6627 }
6628
6629 foreach ($packages as $package) {
6630 if (isset($composer[$type][$package])) {
6631 $json->removeLink($type, $composer[$type][$package]);
6632 } elseif (isset($composer[$altType][$package])) {
6633 $io->writeError('<warning>' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6634 if ($io->isInteractive()) {
6635 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6636 $json->removeLink($altType, $composer[$altType][$package]);
6637 }
6638 }
6639 } elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) {
6640 foreach ($matches as $matchedPackage) {
6641 $json->removeLink($type, $matchedPackage);
6642 }
6643 } elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) {
6644 foreach ($matches as $matchedPackage) {
6645 $io->writeError('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6646 if ($io->isInteractive()) {
6647 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6648 $json->removeLink($altType, $matchedPackage);
6649 }
6650 }
6651 }
6652 } else {
6653 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
6654 }
6655 }
6656
6657 if ($input->getOption('no-update')) {
6658 return 0;
6659 }
6660
6661
6662 $this->resetComposer();
6663 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6664 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6665
6666 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
6667 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6668
6669 $install = Installer::create($io, $composer);
6670
6671 $updateDevMode = !$input->getOption('update-no-dev');
6672 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6673 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6674 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6675
6676 $install
6677 ->setVerbose($input->getOption('verbose'))
6678 ->setDevMode($updateDevMode)
6679 ->setOptimizeAutoloader($optimize)
6680 ->setClassMapAuthoritative($authoritative)
6681 ->setApcuAutoloader($apcu)
6682 ->setUpdate(true)
6683 ->setUpdateAllowList($packages)
6684 ->setAllowListTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
6685 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6686 ->setRunScripts(!$input->getOption('no-scripts'))
6687 ;
6688
6689 $status = $install->run();
6690 if ($status !== 0) {
6691 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
6692 file_put_contents($jsonFile->getPath(), $composerBackup);
6693 }
6694
6695 return $status;
6696 }
6697 }
6698 <?php
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710 namespace Composer\Command;
6711
6712 use Symfony\Component\Console\Input\InputInterface;
6713 use Symfony\Component\Console\Input\InputArgument;
6714 use Symfony\Component\Console\Input\InputOption;
6715 use Symfony\Component\Console\Output\OutputInterface;
6716 use Composer\Factory;
6717 use Composer\Installer;
6718 use Composer\Json\JsonFile;
6719 use Composer\Json\JsonManipulator;
6720 use Composer\Package\Version\VersionParser;
6721 use Composer\Plugin\CommandEvent;
6722 use Composer\Plugin\PluginEvents;
6723 use Composer\Repository\CompositeRepository;
6724 use Composer\Repository\PlatformRepository;
6725 use Composer\IO\IOInterface;
6726 use Composer\Util\Silencer;
6727
6728
6729
6730
6731
6732 class RequireCommand extends InitCommand
6733 {
6734 private $newlyCreated;
6735 private $json;
6736 private $file;
6737 private $composerBackup;
6738
6739 protected function configure()
6740 {
6741 $this
6742 ->setName('require')
6743 ->setDescription('Adds required packages to your composer.json and installs them.')
6744 ->setDefinition(array(
6745 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
6746 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
6747 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
6748 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
6749 new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'),
6750 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6751 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
6752 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6753 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6754 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6755 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
6756 new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
6757 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6758 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
6759 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
6760 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
6761 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6762 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6763 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6764 ))
6765 ->setHelp(
6766 <<<EOT
6767 The require command adds required packages to your composer.json and installs them.
6768
6769 If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of
6770 matches to require.
6771
6772 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
6773
6774 If you do not want to install the new dependencies immediately you can call it with --no-update
6775
6776 Read more at https://getcomposer.org/doc/03-cli.md#require
6777 EOT
6778 )
6779 ;
6780 }
6781
6782 protected function execute(InputInterface $input, OutputInterface $output)
6783 {
6784 if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
6785 pcntl_async_signals(true);
6786 pcntl_signal(SIGINT, array($this, 'revertComposerFile'));
6787 pcntl_signal(SIGTERM, array($this, 'revertComposerFile'));
6788 pcntl_signal(SIGHUP, array($this, 'revertComposerFile'));
6789 }
6790
6791 $this->file = Factory::getComposerFile();
6792 $io = $this->getIO();
6793
6794 $this->newlyCreated = !file_exists($this->file);
6795 if ($this->newlyCreated && !file_put_contents($this->file, "{\n}\n")) {
6796 $io->writeError('<error>'.$this->file.' could not be created.</error>');
6797
6798 return 1;
6799 }
6800
6801
6802 if (!is_readable($this->file) && false === Silencer::call('file_get_contents', $this->file)) {
6803 $io->writeError('<error>'.$this->file.' is not readable.</error>');
6804
6805 return 1;
6806 }
6807
6808 if (filesize($this->file) === 0) {
6809 file_put_contents($this->file, "{\n}\n");
6810 }
6811
6812 $this->json = new JsonFile($this->file);
6813 $this->composerBackup = file_get_contents($this->json->getPath());
6814
6815
6816
6817 if (!is_writable($this->file) && !Silencer::call('file_put_contents', $this->file, $this->composerBackup)) {
6818 $io->writeError('<error>'.$this->file.' is not writable.</error>');
6819
6820 return 1;
6821 }
6822
6823 if ($input->getOption('fixed') === true) {
6824 $config = $this->json->read();
6825
6826 $packageType = empty($config['type']) ? 'library' : $config['type'];
6827
6828
6829
6830
6831 if ($packageType !== 'project') {
6832 $io->writeError('<error>"--fixed" option is allowed for "project" package types only to prevent possible misuses.</error>');
6833
6834 if (empty($config['type'])) {
6835 $io->writeError('<error>If your package is not library, you should explicitly specify "type" parameter in composer.json.</error>');
6836 }
6837
6838 return 1;
6839 }
6840 }
6841
6842 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6843 $repos = $composer->getRepositoryManager()->getRepositories();
6844
6845 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6846
6847 $this->repos = new CompositeRepository(array_merge(
6848 array(new PlatformRepository(array(), $platformOverrides)),
6849 $repos
6850 ));
6851
6852 if ($composer->getPackage()->getPreferStable()) {
6853 $preferredStability = 'stable';
6854 } else {
6855 $preferredStability = $composer->getPackage()->getMinimumStability();
6856 }
6857
6858 $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
6859 try {
6860 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'), $input->getOption('fixed'));
6861 } catch (\Exception $e) {
6862 if ($this->newlyCreated) {
6863 throw new \RuntimeException('No composer.json present in the current directory, this may be the cause of the following exception.', 0, $e);
6864 }
6865
6866 throw $e;
6867 }
6868
6869 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
6870 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
6871 $requirements = $this->formatRequirements($requirements);
6872
6873
6874 $versionParser = new VersionParser();
6875 foreach ($requirements as $package => $constraint) {
6876 if (strtolower($package) === $composer->getPackage()->getName()) {
6877 $io->writeError(sprintf('<error>Root package \'%s\' cannot require itself in its composer.json</error>', $package));
6878
6879 return 1;
6880 }
6881 $versionParser->parseConstraints($constraint);
6882 }
6883
6884 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
6885
6886 if (!$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
6887 $composerDefinition = $this->json->read();
6888 foreach ($requirements as $package => $version) {
6889 $composerDefinition[$requireKey][$package] = $version;
6890 unset($composerDefinition[$removeKey][$package]);
6891 }
6892 $this->json->write($composerDefinition);
6893 }
6894
6895 $io->writeError('<info>'.$this->file.' has been '.($this->newlyCreated ? 'created' : 'updated').'</info>');
6896
6897 if ($input->getOption('no-update')) {
6898 return 0;
6899 }
6900
6901 try {
6902 return $this->doUpdate($input, $output, $io, $requirements);
6903 } catch (\Exception $e) {
6904 $this->revertComposerFile(false);
6905 throw $e;
6906 }
6907 }
6908
6909 private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
6910 {
6911
6912 $this->resetComposer();
6913 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6914 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6915
6916 $updateDevMode = !$input->getOption('update-no-dev');
6917 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6918 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6919 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6920
6921 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
6922 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6923
6924 $install = Installer::create($io, $composer);
6925
6926 $install
6927 ->setVerbose($input->getOption('verbose'))
6928 ->setPreferSource($input->getOption('prefer-source'))
6929 ->setPreferDist($input->getOption('prefer-dist'))
6930 ->setDevMode($updateDevMode)
6931 ->setRunScripts(!$input->getOption('no-scripts'))
6932 ->setSkipSuggest($input->getOption('no-suggest'))
6933 ->setOptimizeAutoloader($optimize)
6934 ->setClassMapAuthoritative($authoritative)
6935 ->setApcuAutoloader($apcu)
6936 ->setUpdate(true)
6937 ->setUpdateAllowList(array_keys($requirements))
6938 ->setAllowListTransitiveDependencies($input->getOption('update-with-dependencies'))
6939 ->setAllowListAllDependencies($input->getOption('update-with-all-dependencies'))
6940 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6941 ->setPreferStable($input->getOption('prefer-stable'))
6942 ->setPreferLowest($input->getOption('prefer-lowest'))
6943 ;
6944
6945 $status = $install->run();
6946 if ($status !== 0) {
6947 $this->revertComposerFile(false);
6948 }
6949
6950 return $status;
6951 }
6952
6953 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
6954 {
6955 $contents = file_get_contents($json->getPath());
6956
6957 $manipulator = new JsonManipulator($contents);
6958
6959 foreach ($new as $package => $constraint) {
6960 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
6961 return false;
6962 }
6963 if (!$manipulator->removeSubNode($removeKey, $package)) {
6964 return false;
6965 }
6966 }
6967
6968 file_put_contents($json->getPath(), $manipulator->getContents());
6969
6970 return true;
6971 }
6972
6973 protected function interact(InputInterface $input, OutputInterface $output)
6974 {
6975 return;
6976 }
6977
6978 public function revertComposerFile($hardExit = true)
6979 {
6980 $io = $this->getIO();
6981
6982 if ($this->newlyCreated) {
6983 $io->writeError("\n".'<error>Installation failed, deleting '.$this->file.'.</error>');
6984 unlink($this->json->getPath());
6985 } else {
6986 $io->writeError("\n".'<error>Installation failed, reverting '.$this->file.' to its original content.</error>');
6987 file_put_contents($this->json->getPath(), $this->composerBackup);
6988 }
6989
6990 if ($hardExit) {
6991 exit(1);
6992 }
6993 }
6994 }
6995 <?php
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007 namespace Composer\Command;
7008
7009 use Composer\Script\Event as ScriptEvent;
7010 use Composer\Script\ScriptEvents;
7011 use Composer\Util\ProcessExecutor;
7012 use Symfony\Component\Console\Input\InputInterface;
7013 use Symfony\Component\Console\Input\InputOption;
7014 use Symfony\Component\Console\Input\InputArgument;
7015 use Symfony\Component\Console\Output\OutputInterface;
7016 use Symfony\Component\Console\Helper\Table;
7017
7018
7019
7020
7021 class RunScriptCommand extends BaseCommand
7022 {
7023
7024
7025
7026 protected $scriptEvents = array(
7027 ScriptEvents::PRE_INSTALL_CMD,
7028 ScriptEvents::POST_INSTALL_CMD,
7029 ScriptEvents::PRE_UPDATE_CMD,
7030 ScriptEvents::POST_UPDATE_CMD,
7031 ScriptEvents::PRE_STATUS_CMD,
7032 ScriptEvents::POST_STATUS_CMD,
7033 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
7034 ScriptEvents::POST_CREATE_PROJECT_CMD,
7035 ScriptEvents::PRE_ARCHIVE_CMD,
7036 ScriptEvents::POST_ARCHIVE_CMD,
7037 ScriptEvents::PRE_AUTOLOAD_DUMP,
7038 ScriptEvents::POST_AUTOLOAD_DUMP,
7039 );
7040
7041 protected function configure()
7042 {
7043 $this
7044 ->setName('run-script')
7045 ->setAliases(array('run'))
7046 ->setDescription('Runs the scripts defined in composer.json.')
7047 ->setDefinition(array(
7048 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
7049 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
7050 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
7051 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
7052 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
7053 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
7054 ))
7055 ->setHelp(
7056 <<<EOT
7057 The <info>run-script</info> command runs scripts defined in composer.json:
7058
7059 <info>php composer.phar run-script post-update-cmd</info>
7060
7061 Read more at https://getcomposer.org/doc/03-cli.md#run-script
7062 EOT
7063 )
7064 ;
7065 }
7066
7067 protected function execute(InputInterface $input, OutputInterface $output)
7068 {
7069 if ($input->getOption('list')) {
7070 return $this->listScripts($output);
7071 } elseif (!$input->getArgument('script')) {
7072 throw new \RuntimeException('Missing required argument "script"');
7073 }
7074
7075 $script = $input->getArgument('script');
7076 if (!in_array($script, $this->scriptEvents)) {
7077 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
7078 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
7079 }
7080 }
7081
7082 $composer = $this->getComposer();
7083 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
7084 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
7085 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
7086 if (!$hasListeners) {
7087 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
7088 }
7089
7090 $args = $input->getArgument('args');
7091
7092 if (null !== $timeout = $input->getOption('timeout')) {
7093 if (!ctype_digit($timeout)) {
7094 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
7095 }
7096
7097 ProcessExecutor::setTimeout((int) $timeout);
7098 }
7099
7100 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
7101 }
7102
7103 protected function listScripts(OutputInterface $output)
7104 {
7105 $scripts = $this->getComposer()->getPackage()->getScripts();
7106
7107 if (!count($scripts)) {
7108 return 0;
7109 }
7110
7111 $io = $this->getIO();
7112 $io->writeError('<info>scripts:</info>');
7113 $table = array();
7114 foreach ($scripts as $name => $script) {
7115 $description = '';
7116 try {
7117 $cmd = $this->getApplication()->find($name);
7118 if ($cmd instanceof ScriptAliasCommand) {
7119 $description = $cmd->getDescription();
7120 }
7121 } catch (\Symfony\Component\Console\Exception\CommandNotFoundException $e) {
7122
7123 }
7124 $table[] = array('  '.$name, $description);
7125 }
7126
7127 $renderer = new Table($output);
7128 $renderer->setStyle('compact');
7129 $rendererStyle = $renderer->getStyle();
7130 if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
7131 $rendererStyle->setVerticalBorderChars('');
7132 } else {
7133 $rendererStyle->setVerticalBorderChar('');
7134 }
7135 $rendererStyle->setCellRowContentFormat('%s  ');
7136 $renderer->setRows($table)->render();
7137
7138 return 0;
7139 }
7140 }
7141 <?php
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153 namespace Composer\Command;
7154
7155 use Symfony\Component\Console\Input\InputInterface;
7156 use Symfony\Component\Console\Input\InputOption;
7157 use Symfony\Component\Console\Input\InputArgument;
7158 use Symfony\Component\Console\Output\OutputInterface;
7159
7160
7161
7162
7163 class ScriptAliasCommand extends BaseCommand
7164 {
7165 private $script;
7166 private $description;
7167
7168 public function __construct($script, $description)
7169 {
7170 $this->script = $script;
7171 $this->description = empty($description) ? 'Runs the '.$script.' script as defined in composer.json.' : $description;
7172
7173 parent::__construct();
7174 }
7175
7176 protected function configure()
7177 {
7178 $this
7179 ->setName($this->script)
7180 ->setDescription($this->description)
7181 ->setDefinition(array(
7182 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
7183 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
7184 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
7185 ))
7186 ->setHelp(
7187 <<<EOT
7188 The <info>run-script</info> command runs scripts defined in composer.json:
7189
7190 <info>php composer.phar run-script post-update-cmd</info>
7191
7192 Read more at https://getcomposer.org/doc/03-cli.md#run-script
7193 EOT
7194 )
7195 ;
7196 }
7197
7198 protected function execute(InputInterface $input, OutputInterface $output)
7199 {
7200 $composer = $this->getComposer();
7201
7202 $args = $input->getArguments();
7203
7204 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
7205 }
7206 }
7207 <?php
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219 namespace Composer\Command;
7220
7221 use Composer\Factory;
7222 use Symfony\Component\Console\Input\InputInterface;
7223 use Symfony\Component\Console\Input\InputArgument;
7224 use Symfony\Component\Console\Input\InputOption;
7225 use Symfony\Component\Console\Output\OutputInterface;
7226 use Composer\Repository\CompositeRepository;
7227 use Composer\Repository\PlatformRepository;
7228 use Composer\Repository\RepositoryInterface;
7229 use Composer\Plugin\CommandEvent;
7230 use Composer\Plugin\PluginEvents;
7231
7232
7233
7234
7235 class SearchCommand extends BaseCommand
7236 {
7237 protected $matches;
7238 protected $lowMatches = array();
7239 protected $tokens;
7240 protected $output;
7241 protected $onlyName;
7242
7243 protected function configure()
7244 {
7245 $this
7246 ->setName('search')
7247 ->setDescription('Searches for packages.')
7248 ->setDefinition(array(
7249 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
7250 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
7251 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
7252 ))
7253 ->setHelp(
7254 <<<EOT
7255 The search command searches for packages by its name
7256 <info>php composer.phar search symfony composer</info>
7257
7258 Read more at https://getcomposer.org/doc/03-cli.md#search
7259 EOT
7260 )
7261 ;
7262 }
7263
7264 protected function execute(InputInterface $input, OutputInterface $output)
7265 {
7266
7267 $platformRepo = new PlatformRepository;
7268 $io = $this->getIO();
7269 if (!($composer = $this->getComposer(false))) {
7270 $composer = Factory::create($this->getIO(), array(), $input->hasParameterOption('--no-plugins'));
7271 }
7272 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
7273 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
7274 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
7275
7276 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
7277 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7278
7279 $onlyName = $input->getOption('only-name');
7280 $type = $input->getOption('type') ?: null;
7281
7282 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
7283 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
7284
7285 foreach ($results as $result) {
7286 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
7287 }
7288
7289 return 0;
7290 }
7291 }
7292 <?php
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304 namespace Composer\Command;
7305
7306 use Composer\Composer;
7307 use Composer\Factory;
7308 use Composer\Config;
7309 use Composer\Util\Filesystem;
7310 use Composer\Util\Platform;
7311 use Composer\SelfUpdate\Keys;
7312 use Composer\SelfUpdate\Versions;
7313 use Composer\IO\IOInterface;
7314 use Composer\Downloader\FilesystemException;
7315 use Symfony\Component\Console\Input\InputInterface;
7316 use Symfony\Component\Console\Input\InputOption;
7317 use Symfony\Component\Console\Input\InputArgument;
7318 use Symfony\Component\Console\Output\OutputInterface;
7319 use Symfony\Component\Finder\Finder;
7320
7321
7322
7323
7324
7325
7326 class SelfUpdateCommand extends BaseCommand
7327 {
7328 const HOMEPAGE = 'getcomposer.org';
7329 const OLD_INSTALL_EXT = '-old.phar';
7330
7331 protected function configure()
7332 {
7333 $this
7334 ->setName('self-update')
7335 ->setAliases(array('selfupdate'))
7336 ->setDescription('Updates composer.phar to the latest version.')
7337 ->setDefinition(array(
7338 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
7339 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'),
7340 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
7341 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
7342 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
7343 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
7344 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
7345 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
7346 new InputOption('1', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 1.x versions'),
7347 new InputOption('2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.x versions'),
7348 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
7349 ))
7350 ->setHelp(
7351 <<<EOT
7352 The <info>self-update</info> command checks getcomposer.org for newer
7353 versions of composer and if found, installs the latest.
7354
7355 <info>php composer.phar self-update</info>
7356
7357 Read more at https://getcomposer.org/doc/03-cli.md#self-update-selfupdate-
7358 EOT
7359 )
7360 ;
7361 }
7362
7363 protected function execute(InputInterface $input, OutputInterface $output)
7364 {
7365 $config = Factory::createConfig();
7366
7367 if ($config->get('disable-tls') === true) {
7368 $baseUrl = 'http://' . self::HOMEPAGE;
7369 } else {
7370 $baseUrl = 'https://' . self::HOMEPAGE;
7371 }
7372
7373 $io = $this->getIO();
7374 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
7375
7376 $versionsUtil = new Versions($config, $remoteFilesystem);
7377
7378
7379 $requestedChannel = null;
7380 foreach (Versions::$channels as $channel) {
7381 if ($input->getOption($channel)) {
7382 $requestedChannel = $channel;
7383 $versionsUtil->setChannel($channel);
7384 break;
7385 }
7386 }
7387
7388 if ($input->getOption('set-channel-only')) {
7389 return 0;
7390 }
7391
7392 $cacheDir = $config->get('cache-dir');
7393 $rollbackDir = $config->get('data-dir');
7394 $home = $config->get('home');
7395 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
7396
7397 if ($input->getOption('update-keys')) {
7398 $this->fetchKeys($io, $config);
7399
7400 return 0;
7401 }
7402
7403
7404 if (!file_exists($localFilename)) {
7405 throw new FilesystemException('Composer update failed: the "'.$localFilename.'" is not accessible');
7406 }
7407
7408
7409 $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
7410
7411
7412 if (!is_writable($tmpDir)) {
7413 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
7414 }
7415
7416
7417 if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
7418 $composeUser = posix_getpwuid(posix_geteuid());
7419 $homeOwner = posix_getpwuid(fileowner($home));
7420 if (isset($composeUser['name']) && isset($homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
7421 $io->writeError('<warning>You are running composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'"</warning>');
7422 }
7423 }
7424
7425 if ($input->getOption('rollback')) {
7426 return $this->rollback($output, $rollbackDir, $localFilename);
7427 }
7428
7429 $latest = $versionsUtil->getLatest();
7430 $latestStable = $versionsUtil->getLatest('stable');
7431 try {
7432 $latestPreview = $versionsUtil->getLatest('preview');
7433 } catch (\UnexpectedValueException $e) {
7434 $latestPreview = $latestStable;
7435 }
7436 $latestVersion = $latest['version'];
7437 $updateVersion = $input->getArgument('version') ?: $latestVersion;
7438 $currentMajorVersion = preg_replace('{^(\d+).*}', '$1', Composer::getVersion());
7439 $updateMajorVersion = preg_replace('{^(\d+).*}', '$1', $updateVersion);
7440 $previewMajorVersion = preg_replace('{^(\d+).*}', '$1', $latestPreview['version']);
7441
7442 if ($versionsUtil->getChannel() === 'stable' && !$input->getArgument('version')) {
7443
7444
7445 if ($currentMajorVersion < $updateMajorVersion) {
7446 $skippedVersion = $updateVersion;
7447
7448 $versionsUtil->setChannel($currentMajorVersion);
7449
7450 $latest = $versionsUtil->getLatest();
7451 $latestStable = $versionsUtil->getLatest('stable');
7452 $latestVersion = $latest['version'];
7453 $updateVersion = $latestVersion;
7454
7455 $io->writeError('<warning>A new stable major version of Composer is available ('.$skippedVersion.'), run "composer self-update --'.$updateMajorVersion.'" to update to it. See also https://getcomposer.org/'.$updateMajorVersion.'</warning>');
7456 } elseif ($currentMajorVersion < $previewMajorVersion) {
7457
7458 $io->writeError('<warning>A preview release of the next major version of Composer is available ('.$latestPreview['version'].'), run "composer self-update --preview" to give it a try. See also https://github.com/composer/composer/releases for changelogs.</warning>');
7459 }
7460 }
7461
7462 if ($requestedChannel && is_numeric($requestedChannel) && substr($latestStable['version'], 0, 1) !== $requestedChannel) {
7463 $io->writeError('<warning>Warning: You forced the install of '.$latestVersion.' via --'.$requestedChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.</warning>');
7464 }
7465
7466 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
7467 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
7468
7469 return 1;
7470 }
7471
7472 $channelString = $versionsUtil->getChannel();
7473 if (is_numeric($channelString)) {
7474 $channelString .= '.x';
7475 }
7476
7477 if (Composer::VERSION === $updateVersion) {
7478 $io->writeError(
7479 sprintf(
7480 '<info>You are already using composer version %s (%s channel).</info>',
7481 $updateVersion,
7482 $channelString
7483 )
7484 );
7485
7486
7487 if ($input->getOption('clean-backups')) {
7488 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
7489 }
7490
7491 return 0;
7492 }
7493
7494 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
7495 $backupFile = sprintf(
7496 '%s/%s-%s%s',
7497 $rollbackDir,
7498 strtr(Composer::RELEASE_DATE, ' :', '_-'),
7499 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
7500 self::OLD_INSTALL_EXT
7501 );
7502
7503 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
7504
7505 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $channelString));
7506 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
7507 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
7508 $io->writeError('   ', false);
7509 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
7510 $io->writeError('');
7511
7512 if (!file_exists($tempFilename) || !$signature) {
7513 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
7514
7515 return 1;
7516 }
7517
7518
7519 if (!extension_loaded('openssl') && $config->get('disable-tls')) {
7520 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
7521 } else {
7522 if (!extension_loaded('openssl')) {
7523 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
7524 . '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.');
7525 }
7526
7527 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
7528 if (!file_exists($sigFile)) {
7529 file_put_contents(
7530 $home.'/keys.dev.pub',
7531 <<<DEVPUBKEY
7532 -----BEGIN PUBLIC KEY-----
7533 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
7534 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
7535 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
7536 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
7537 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
7538 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
7539 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
7540 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
7541 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
7542 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
7543 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
7544 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
7545 -----END PUBLIC KEY-----
7546 DEVPUBKEY
7547 );
7548
7549 file_put_contents(
7550 $home.'/keys.tags.pub',
7551 <<<TAGSPUBKEY
7552 -----BEGIN PUBLIC KEY-----
7553 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
7554 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
7555 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
7556 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
7557 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
7558 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
7559 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
7560 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
7561 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
7562 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
7563 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
7564 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
7565 -----END PUBLIC KEY-----
7566 TAGSPUBKEY
7567 );
7568 }
7569
7570 $pubkeyid = openssl_pkey_get_public($sigFile);
7571 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
7572 if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) {
7573 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
7574 }
7575 $signature = json_decode($signature, true);
7576 $signature = base64_decode($signature['sha384']);
7577 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
7578
7579
7580 if (PHP_VERSION_ID < 80000) {
7581 openssl_free_key($pubkeyid);
7582 }
7583
7584 if (!$verified) {
7585 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');
7586 }
7587 }
7588
7589
7590 if ($input->getOption('clean-backups')) {
7591 $this->cleanBackups($rollbackDir);
7592 }
7593
7594 if (!$this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
7595 @unlink($tempFilename);
7596
7597 return 1;
7598 }
7599
7600 if (file_exists($backupFile)) {
7601 $io->writeError(sprintf(
7602 'Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>',
7603 Composer::VERSION
7604 ));
7605 } else {
7606 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
7607 }
7608
7609 return 0;
7610 }
7611
7612 protected function fetchKeys(IOInterface $io, Config $config)
7613 {
7614 if (!$io->isInteractive()) {
7615 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
7616 }
7617
7618 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
7619
7620 $validator = function ($value) {
7621 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
7622 throw new \UnexpectedValueException('Invalid input');
7623 }
7624
7625 return trim($value)."\n";
7626 };
7627
7628 $devKey = '';
7629 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
7630 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
7631 while ($line = $io->ask('')) {
7632 $devKey .= trim($line)."\n";
7633 if (trim($line) === '-----END PUBLIC KEY-----') {
7634 break;
7635 }
7636 }
7637 }
7638 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
7639 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7640
7641 $tagsKey = '';
7642 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
7643 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
7644 while ($line = $io->ask('')) {
7645 $tagsKey .= trim($line)."\n";
7646 if (trim($line) === '-----END PUBLIC KEY-----') {
7647 break;
7648 }
7649 }
7650 }
7651 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
7652 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7653
7654 $io->write('Public keys stored in '.$config->get('home'));
7655 }
7656
7657 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
7658 {
7659 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
7660 if (!$rollbackVersion) {
7661 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
7662 }
7663
7664 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
7665
7666 if (!is_file($oldFile)) {
7667 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
7668 }
7669 if (!is_readable($oldFile)) {
7670 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
7671 }
7672
7673 $io = $this->getIO();
7674 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
7675 if (!$this->setLocalPhar($localFilename, $oldFile)) {
7676 return 1;
7677 }
7678
7679 return 0;
7680 }
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
7692 {
7693 $io = $this->getIO();
7694 @chmod($newFilename, fileperms($localFilename));
7695
7696
7697 if (!$this->validatePhar($newFilename, $error)) {
7698 $io->writeError('<error>The '.($backupTarget ? 'update' : 'backup').' file is corrupted ('.$error.')</error>');
7699
7700 if ($backupTarget) {
7701 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
7702 }
7703
7704 return false;
7705 }
7706
7707
7708 if ($backupTarget) {
7709 @copy($localFilename, $backupTarget);
7710 }
7711
7712 try {
7713 if (Platform::isWindows()) {
7714
7715
7716 copy($newFilename, $localFilename);
7717 @unlink($newFilename);
7718 } else {
7719 rename($newFilename, $localFilename);
7720 }
7721
7722 return true;
7723 } catch (\Exception $e) {
7724
7725 if (!is_writable(dirname($localFilename))
7726 && $io->isInteractive()
7727 && $this->isWindowsNonAdminUser()) {
7728 return $this->tryAsWindowsAdmin($localFilename, $newFilename);
7729 }
7730
7731 @unlink($newFilename);
7732 $action = 'Composer '.($backupTarget ? 'update' : 'rollback');
7733 throw new FilesystemException($action.' failed: "'.$localFilename.'" could not be written.'.PHP_EOL.$e->getMessage());
7734 }
7735 }
7736
7737 protected function cleanBackups($rollbackDir, $except = null)
7738 {
7739 $finder = $this->getOldInstallationFinder($rollbackDir);
7740 $io = $this->getIO();
7741 $fs = new Filesystem;
7742
7743 foreach ($finder as $file) {
7744 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
7745 continue;
7746 }
7747 $file = (string) $file;
7748 $io->writeError('<info>Removing: '.$file.'</info>');
7749 $fs->remove($file);
7750 }
7751 }
7752
7753 protected function getLastBackupVersion($rollbackDir)
7754 {
7755 $finder = $this->getOldInstallationFinder($rollbackDir);
7756 $finder->sortByName();
7757 $files = iterator_to_array($finder);
7758
7759 if (count($files)) {
7760 return basename(end($files), self::OLD_INSTALL_EXT);
7761 }
7762
7763 return false;
7764 }
7765
7766 protected function getOldInstallationFinder($rollbackDir)
7767 {
7768 $finder = Finder::create()
7769 ->depth(0)
7770 ->files()
7771 ->name('*' . self::OLD_INSTALL_EXT)
7772 ->in($rollbackDir);
7773
7774 return $finder;
7775 }
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789 protected function validatePhar($pharFile, &$error)
7790 {
7791 if (ini_get('phar.readonly')) {
7792 return true;
7793 }
7794
7795 try {
7796
7797 $phar = new \Phar($pharFile);
7798
7799 unset($phar);
7800 $result = true;
7801 } catch (\Exception $e) {
7802 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
7803 throw $e;
7804 }
7805 $error = $e->getMessage();
7806 $result = false;
7807 }
7808
7809 return $result;
7810 }
7811
7812
7813
7814
7815
7816
7817 protected function isWindowsNonAdminUser()
7818 {
7819 if (!Platform::isWindows()) {
7820 return false;
7821 }
7822
7823
7824 exec('fltmc.exe filters', $output, $exitCode);
7825
7826 return $exitCode !== 0;
7827 }
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838 protected function tryAsWindowsAdmin($localFilename, $newFilename)
7839 {
7840 $io = $this->getIO();
7841
7842 $io->writeError('<error>Unable to write "'.$localFilename.'". Access is denied.</error>');
7843 $helpMessage = 'Please run the self-update command as an Administrator.';
7844 $question = 'Complete this operation with Administrator privileges [<comment>Y,n</comment>]? ';
7845
7846 if (!$io->askConfirmation($question, false)) {
7847 $io->writeError('<warning>Operation cancelled. '.$helpMessage.'</warning>');
7848
7849 return false;
7850 }
7851
7852 $tmpFile = tempnam(sys_get_temp_dir(), '');
7853 $script = $tmpFile.'.vbs';
7854 rename($tmpFile, $script);
7855
7856 $checksum = hash_file('sha256', $newFilename);
7857
7858
7859 $source = str_replace('/', '\\', $newFilename);
7860 $destination = str_replace('/', '\\', $localFilename);
7861
7862 $vbs = <<<EOT
7863 Set UAC = CreateObject("Shell.Application")
7864 UAC.ShellExecute "cmd.exe", "/c copy /b /y ""$source"" ""$destination""", "", "runas", 0
7865 Wscript.Sleep(300)
7866 EOT;
7867
7868 file_put_contents($script, $vbs);
7869 exec('"'.$script.'"');
7870 @unlink($script);
7871
7872
7873 if ($result = is_readable($localFilename) && (hash_file('sha256', $localFilename) === $checksum)) {
7874 $io->writeError('<info>Operation succeeded.</info>');
7875 @unlink($newFilename);
7876 } else {
7877 $io->writeError('<error>Operation failed.'.$helpMessage.'</error>');
7878 }
7879
7880 return $result;
7881 }
7882 }
7883 <?php
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895 namespace Composer\Command;
7896
7897 use Composer\Composer;
7898 use Composer\DependencyResolver\DefaultPolicy;
7899 use Composer\DependencyResolver\Pool;
7900 use Composer\Json\JsonFile;
7901 use Composer\Package\BasePackage;
7902 use Composer\Package\CompletePackageInterface;
7903 use Composer\Package\PackageInterface;
7904 use Composer\Package\Version\VersionParser;
7905 use Composer\Package\Version\VersionSelector;
7906 use Composer\Plugin\CommandEvent;
7907 use Composer\Plugin\PluginEvents;
7908 use Composer\Repository\ArrayRepository;
7909 use Composer\Repository\ComposerRepository;
7910 use Composer\Repository\CompositeRepository;
7911 use Composer\Repository\PlatformRepository;
7912 use Composer\Repository\RepositoryFactory;
7913 use Composer\Repository\RepositoryInterface;
7914 use Composer\Semver\Constraint\ConstraintInterface;
7915 use Composer\Semver\Semver;
7916 use Composer\Spdx\SpdxLicenses;
7917 use Composer\Util\Platform;
7918 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
7919 use Symfony\Component\Console\Input\InputArgument;
7920 use Symfony\Component\Console\Input\InputInterface;
7921 use Symfony\Component\Console\Input\InputOption;
7922 use Symfony\Component\Console\Output\OutputInterface;
7923 use Symfony\Component\Console\Terminal;
7924
7925
7926
7927
7928
7929
7930
7931 class ShowCommand extends BaseCommand
7932 {
7933
7934 protected $versionParser;
7935 protected $colors;
7936
7937
7938 private $pool;
7939
7940 protected function configure()
7941 {
7942 $this
7943 ->setName('show')
7944 ->setAliases(array('info'))
7945 ->setDescription('Shows information about packages.')
7946 ->setDefinition(array(
7947 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
7948 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
7949 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
7950 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
7951 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
7952 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
7953 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
7954 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
7955 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
7956 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
7957 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
7958 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
7959 new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.'),
7960 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
7961 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
7962 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
7963 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
7964 ))
7965 ->setHelp(
7966 <<<EOT
7967 The show command displays detailed information about a package, or
7968 lists all packages available.
7969
7970 Read more at https://getcomposer.org/doc/03-cli.md#show
7971 EOT
7972 )
7973 ;
7974 }
7975
7976 protected function execute(InputInterface $input, OutputInterface $output)
7977 {
7978 $this->versionParser = new VersionParser;
7979 if ($input->getOption('tree')) {
7980 $this->initStyles($output);
7981 }
7982
7983 $composer = $this->getComposer(false);
7984 $io = $this->getIO();
7985
7986 if ($input->getOption('installed')) {
7987 $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>');
7988 }
7989
7990 if ($input->getOption('outdated')) {
7991 $input->setOption('latest', true);
7992 } elseif ($input->getOption('ignore')) {
7993 $io->writeError('<warning>You are using the option "ignore" for action other than "outdated", it will be ignored.</warning>');
7994 }
7995
7996 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
7997 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
7998
7999 return 1;
8000 }
8001
8002 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
8003 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
8004
8005 return 1;
8006 }
8007
8008 if ($input->getOption('tree') && $input->getOption('latest')) {
8009 $io->writeError('The --tree (-t) option is not usable in combination with --latest (-l)');
8010
8011 return 1;
8012 }
8013
8014 if ($input->getOption('tree') && $input->getOption('path')) {
8015 $io->writeError('The --tree (-t) option is not usable in combination with --path (-P)');
8016
8017 return 1;
8018 }
8019
8020 $format = $input->getOption('format');
8021 if (!in_array($format, array('text', 'json'))) {
8022 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
8023
8024 return 1;
8025 }
8026
8027
8028 $platformOverrides = array();
8029 if ($composer) {
8030 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
8031 }
8032 $platformRepo = new PlatformRepository(array(), $platformOverrides);
8033 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
8034
8035 if ($input->getOption('self')) {
8036 $package = $this->getComposer()->getPackage();
8037 if ($input->getOption('name-only')) {
8038 $io->write($package->getName());
8039 return 0;
8040 }
8041 $repos = $installedRepo = new ArrayRepository(array($package));
8042 } elseif ($input->getOption('platform')) {
8043 $repos = $installedRepo = $platformRepo;
8044 } elseif ($input->getOption('available')) {
8045 $installedRepo = $platformRepo;
8046 if ($composer) {
8047 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
8048 } else {
8049 $defaultRepos = RepositoryFactory::defaultRepos($io);
8050 $repos = new CompositeRepository($defaultRepos);
8051 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
8052 }
8053 } elseif ($input->getOption('all') && $composer) {
8054 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8055 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
8056 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
8057 } elseif ($input->getOption('all')) {
8058 $defaultRepos = RepositoryFactory::defaultRepos($io);
8059 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
8060 $installedRepo = $platformRepo;
8061 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
8062 } else {
8063 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
8064 $rootPkg = $this->getComposer()->getPackage();
8065 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
8066 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
8067 }
8068 }
8069
8070 if ($composer) {
8071 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
8072 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8073 }
8074
8075 if ($input->getOption('latest') && null === $composer) {
8076 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
8077 $input->setOption('latest', false);
8078 }
8079
8080 $packageFilter = $input->getArgument('package');
8081
8082
8083 if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
8084 if (empty($package)) {
8085 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
8086
8087 if (empty($package)) {
8088 $options = $input->getOptions();
8089 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
8090 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $input->getArgument('package')) && !$input->getOption('platform')) {
8091 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found, try using --platform (-p) to show platform packages.');
8092 }
8093 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
8094 }
8095
8096 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
8097
8098 return 1;
8099 }
8100 } else {
8101 $versions = array($package->getPrettyVersion() => $package->getVersion());
8102 }
8103
8104 $exitCode = 0;
8105 if ($input->getOption('tree')) {
8106 $arrayTree = $this->generatePackageTree($package, $installedRepo, $repos);
8107
8108 if ('json' === $format) {
8109 $io->write(JsonFile::encode(array('installed' => array($arrayTree))));
8110 } else {
8111 $this->displayPackageTree(array($arrayTree));
8112 }
8113 } else {
8114 $latestPackage = null;
8115 if ($input->getOption('latest')) {
8116 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
8117 }
8118 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
8119 $exitCode = 1;
8120 }
8121 if ($input->getOption('path')) {
8122 $io->write($package->getName(), false);
8123 $io->write(' ' . strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n"));
8124
8125 return $exitCode;
8126 }
8127
8128 if ('json' === $format) {
8129 $this->printPackageInfoAsJson($package, $versions, $installedRepo, $latestPackage ?: null);
8130 } else {
8131 $this->printPackageInfo($package, $versions, $installedRepo, $latestPackage ?: null);
8132 }
8133 }
8134
8135 return $exitCode;
8136 }
8137
8138
8139 if ($input->getOption('tree')) {
8140 $rootRequires = $this->getRootRequires();
8141 $packages = $installedRepo->getPackages();
8142 usort($packages, 'strcmp');
8143 $arrayTree = array();
8144 foreach ($packages as $package) {
8145 if (in_array($package->getName(), $rootRequires, true)) {
8146 $arrayTree[] = $this->generatePackageTree($package, $installedRepo, $repos);
8147 }
8148 }
8149
8150 if ('json' === $format) {
8151 $io->write(JsonFile::encode(array('installed' => $arrayTree)));
8152 } else {
8153 $this->displayPackageTree($arrayTree);
8154 }
8155
8156 return 0;
8157 }
8158
8159 if ($repos instanceof CompositeRepository) {
8160 $repos = $repos->getRepositories();
8161 } elseif (!is_array($repos)) {
8162 $repos = array($repos);
8163 }
8164
8165
8166 $packages = array();
8167 if (null !== $packageFilter) {
8168 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
8169 }
8170
8171 $packageListFilter = array();
8172 if ($input->getOption('direct')) {
8173 $packageListFilter = $this->getRootRequires();
8174 }
8175
8176 if (class_exists('Symfony\Component\Console\Terminal')) {
8177 $terminal = new Terminal();
8178 $width = $terminal->getWidth();
8179 } else {
8180
8181 list($width) = $this->getApplication()->getTerminalDimensions();
8182 }
8183 if (null === $width) {
8184
8185
8186 $width = PHP_INT_MAX;
8187 }
8188 if (Platform::isWindows()) {
8189 $width--;
8190 } else {
8191 $width = max(80, $width);
8192 }
8193
8194 if ($input->getOption('path') && null === $composer) {
8195 $io->writeError('No composer.json found in the current directory, disabling "path" option');
8196 $input->setOption('path', false);
8197 }
8198
8199 foreach ($repos as $repo) {
8200 if ($repo === $platformRepo) {
8201 $type = 'platform';
8202 } elseif (
8203 $repo === $installedRepo
8204 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
8205 ) {
8206 $type = 'installed';
8207 } else {
8208 $type = 'available';
8209 }
8210 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
8211 foreach ($repo->getProviderNames() as $name) {
8212 if (!$packageFilter || preg_match($packageFilter, $name)) {
8213 $packages[$type][$name] = $name;
8214 }
8215 }
8216 } else {
8217 foreach ($repo->getPackages() as $package) {
8218 if (!isset($packages[$type][$package->getName()])
8219 || !is_object($packages[$type][$package->getName()])
8220 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
8221 ) {
8222 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
8223 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
8224 $packages[$type][$package->getName()] = $package;
8225 }
8226 }
8227 }
8228 }
8229 }
8230 }
8231
8232 $showAllTypes = $input->getOption('all');
8233 $showLatest = $input->getOption('latest');
8234 $showMinorOnly = $input->getOption('minor-only');
8235 $ignoredPackages = array_map('strtolower', $input->getOption('ignore'));
8236 $indent = $showAllTypes ? '  ' : '';
8237 $latestPackages = array();
8238 $exitCode = 0;
8239 $viewData = array();
8240 $viewMetaData = array();
8241 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
8242 if (isset($packages[$type])) {
8243 ksort($packages[$type]);
8244
8245 $nameLength = $versionLength = $latestLength = 0;
8246
8247 if ($showLatest && $showVersion) {
8248 foreach ($packages[$type] as $package) {
8249 if (is_object($package)) {
8250 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
8251 if ($latestPackage === false) {
8252 continue;
8253 }
8254
8255 $latestPackages[$package->getPrettyName()] = $latestPackage;
8256 }
8257 }
8258 }
8259
8260 $writePath = !$input->getOption('name-only') && $input->getOption('path');
8261 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
8262 $writeLatest = $writeVersion && $showLatest;
8263 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
8264
8265 $hasOutdatedPackages = false;
8266
8267 $viewData[$type] = array();
8268 foreach ($packages[$type] as $package) {
8269 $packageViewData = array();
8270 if (is_object($package)) {
8271 $latestPackage = null;
8272 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
8273 $latestPackage = $latestPackages[$package->getPrettyName()];
8274 }
8275
8276
8277 $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned();
8278 $packageIsIgnored = \in_array($package->getPrettyName(), $ignoredPackages, true);
8279 if ($input->getOption('outdated') && ($packageIsUpToDate || $packageIsIgnored)) {
8280 continue;
8281 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
8282 $hasOutdatedPackages = true;
8283 }
8284
8285 $packageViewData['name'] = $package->getPrettyName();
8286 $nameLength = max($nameLength, strlen($package->getPrettyName()));
8287 if ($writeVersion) {
8288 $packageViewData['version'] = $package->getFullPrettyVersion();
8289 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
8290 }
8291 if ($writeLatest && $latestPackage) {
8292 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
8293 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
8294 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
8295 }
8296 if ($writeDescription) {
8297 $packageViewData['description'] = $package->getDescription();
8298 }
8299 if ($writePath) {
8300 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
8301 }
8302
8303 if ($latestPackage && $latestPackage->isAbandoned()) {
8304 $replacement = is_string($latestPackage->getReplacementPackage())
8305 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
8306 : 'No replacement was suggested';
8307 $packageWarning = sprintf(
8308 'Package %s is abandoned, you should avoid using it. %s.',
8309 $package->getPrettyName(),
8310 $replacement
8311 );
8312 $packageViewData['warning'] = $packageWarning;
8313 }
8314 } else {
8315 $packageViewData['name'] = $package;
8316 $nameLength = max($nameLength, strlen($package));
8317 }
8318 $viewData[$type][] = $packageViewData;
8319 }
8320 $viewMetaData[$type] = array(
8321 'nameLength' => $nameLength,
8322 'versionLength' => $versionLength,
8323 'latestLength' => $latestLength,
8324 );
8325 if ($input->getOption('strict') && $hasOutdatedPackages) {
8326 $exitCode = 1;
8327 break;
8328 }
8329 }
8330 }
8331
8332 if ('json' === $format) {
8333 $io->write(JsonFile::encode($viewData));
8334 } else {
8335 foreach ($viewData as $type => $packages) {
8336 $nameLength = $viewMetaData[$type]['nameLength'];
8337 $versionLength = $viewMetaData[$type]['versionLength'];
8338 $latestLength = $viewMetaData[$type]['latestLength'];
8339
8340 $writeVersion = $nameLength + $versionLength + 3 <= $width;
8341 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
8342 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
8343
8344 if ($writeLatest && !$io->isDecorated()) {
8345 $latestLength += 2;
8346 }
8347
8348 if ($showAllTypes) {
8349 if ('available' === $type) {
8350 $io->write('<comment>' . $type . '</comment>:');
8351 } else {
8352 $io->write('<info>' . $type . '</info>:');
8353 }
8354 }
8355
8356 foreach ($packages as $package) {
8357 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
8358 if (isset($package['version']) && $writeVersion) {
8359 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
8360 }
8361 if (isset($package['latest']) && $writeLatest) {
8362 $latestVersion = $package['latest'];
8363 $updateStatus = $package['latest-status'];
8364 $style = $this->updateStatusToVersionStyle($updateStatus);
8365 if (!$io->isDecorated()) {
8366 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
8367 }
8368 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
8369 }
8370 if (isset($package['description']) && $writeDescription) {
8371 $description = strtok($package['description'], "\r\n");
8372 $remaining = $width - $nameLength - $versionLength - 4;
8373 if ($writeLatest) {
8374 $remaining -= $latestLength;
8375 }
8376 if (strlen($description) > $remaining) {
8377 $description = substr($description, 0, $remaining - 3) . '...';
8378 }
8379 $io->write(' ' . $description, false);
8380 }
8381 if (isset($package['path'])) {
8382 $io->write(' ' . $package['path'], false);
8383 }
8384 $io->write('');
8385 if (isset($package['warning'])) {
8386 $io->write('<warning>' . $package['warning'] . '</warning>');
8387 }
8388 }
8389
8390 if ($showAllTypes) {
8391 $io->write('');
8392 }
8393 }
8394 }
8395
8396 return $exitCode;
8397 }
8398
8399 protected function getRootRequires()
8400 {
8401 $rootPackage = $this->getComposer()->getPackage();
8402
8403 return array_map(
8404 'strtolower',
8405 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
8406 );
8407 }
8408
8409 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
8410 {
8411 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
8412 }
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
8425 {
8426 $name = strtolower($name);
8427 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
8428
8429 $policy = new DefaultPolicy();
8430 $pool = new Pool('dev');
8431 $pool->addRepository($repos);
8432
8433 $matchedPackage = null;
8434 $versions = array();
8435 $matches = $pool->whatProvides($name, $constraint);
8436 foreach ($matches as $index => $package) {
8437
8438 if ($package->getName() !== $name) {
8439 unset($matches[$index]);
8440 continue;
8441 }
8442
8443
8444 if (null === $version && $installedRepo->hasPackage($package)) {
8445 $matchedPackage = $package;
8446 }
8447
8448 $versions[$package->getPrettyVersion()] = $package->getVersion();
8449 $matches[$index] = $package->getId();
8450 }
8451
8452
8453 if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
8454 $matchedPackage = $pool->literalToPackage($preferred[0]);
8455 }
8456
8457 return array($matchedPackage, $versions);
8458 }
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468 protected function printPackageInfo(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
8469 {
8470 $io = $this->getIO();
8471
8472 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
8473 $this->printLinks($package, 'requires');
8474 $this->printLinks($package, 'devRequires', 'requires (dev)');
8475
8476 if ($package->getSuggests()) {
8477 $io->write("\n<info>suggests</info>");
8478 foreach ($package->getSuggests() as $suggested => $reason) {
8479 $io->write($suggested . ' <comment>' . $reason . '</comment>');
8480 }
8481 }
8482
8483 $this->printLinks($package, 'provides');
8484 $this->printLinks($package, 'conflicts');
8485 $this->printLinks($package, 'replaces');
8486 }
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
8497 {
8498 $io = $this->getIO();
8499 $io->write('<info>name</info>     : ' . $package->getPrettyName());
8500 $io->write('<info>descrip.</info> : ' . $package->getDescription());
8501 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
8502 $this->printVersions($package, $versions, $installedRepo);
8503 if ($latestPackage) {
8504 $style = $this->getVersionStyle($latestPackage, $package);
8505 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
8506 } else {
8507 $latestPackage = $package;
8508 }
8509 $io->write('<info>type</info>     : ' . $package->getType());
8510 $this->printLicenses($package);
8511 $io->write('<info>homepage</info> : ' . $package->getHomepage());
8512 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
8513 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
8514 if ($installedRepo->hasPackage($package)) {
8515 $io->write('<info>path</info>     : ' . sprintf('%s', realpath($this->getComposer()->getInstallationManager()->getInstallPath($package))));
8516 }
8517 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
8518
8519 if ($latestPackage->isAbandoned()) {
8520 $replacement = ($latestPackage->getReplacementPackage() !== null)
8521 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
8522 : null;
8523
8524 $io->writeError(
8525 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
8526 );
8527 }
8528
8529 if ($package->getSupport()) {
8530 $io->write("\n<info>support</info>");
8531 foreach ($package->getSupport() as $type => $value) {
8532 $io->write('<comment>' . $type . '</comment> : '.$value);
8533 }
8534 }
8535
8536 if ($package->getAutoload()) {
8537 $io->write("\n<info>autoload</info>");
8538 foreach ($package->getAutoload() as $type => $autoloads) {
8539 $io->write('<comment>' . $type . '</comment>');
8540
8541 if ($type === 'psr-0') {
8542 foreach ($autoloads as $name => $path) {
8543 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
8544 }
8545 } elseif ($type === 'psr-4') {
8546 foreach ($autoloads as $name => $path) {
8547 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
8548 }
8549 } elseif ($type === 'classmap') {
8550 $io->write(implode(', ', $autoloads));
8551 }
8552 }
8553 if ($package->getIncludePaths()) {
8554 $io->write('<comment>include-path</comment>');
8555 $io->write(implode(', ', $package->getIncludePaths()));
8556 }
8557 }
8558 }
8559
8560
8561
8562
8563
8564
8565
8566
8567 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
8568 {
8569 uasort($versions, 'version_compare');
8570 $versions = array_keys(array_reverse($versions));
8571
8572
8573 if ($installedRepo->hasPackage($package)) {
8574 $installedVersion = $package->getPrettyVersion();
8575 $key = array_search($installedVersion, $versions);
8576 if (false !== $key) {
8577 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
8578 }
8579 }
8580
8581 $versions = implode(', ', $versions);
8582
8583 $this->getIO()->write('<info>versions</info> : ' . $versions);
8584 }
8585
8586
8587
8588
8589
8590
8591
8592
8593 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
8594 {
8595 $title = $title ?: $linkType;
8596 $io = $this->getIO();
8597 if ($links = $package->{'get'.ucfirst($linkType)}()) {
8598 $io->write("\n<info>" . $title . "</info>");
8599
8600 foreach ($links as $link) {
8601 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
8602 }
8603 }
8604 }
8605
8606
8607
8608
8609
8610
8611 protected function printLicenses(CompletePackageInterface $package)
8612 {
8613 $spdxLicenses = new SpdxLicenses();
8614
8615 $licenses = $package->getLicense();
8616 $io = $this->getIO();
8617
8618 foreach ($licenses as $licenseId) {
8619 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
8620
8621 if (!$license) {
8622 $out = $licenseId;
8623 } else {
8624
8625 if ($license[1] === true) {
8626 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
8627 } else {
8628 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
8629 }
8630 }
8631
8632 $io->write('<info>license</info>  : ' . $out);
8633 }
8634 }
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644 protected function printPackageInfoAsJson(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
8645 {
8646 $json = array(
8647 'name' => $package->getPrettyName(),
8648 'description' => $package->getDescription(),
8649 'keywords' => $package->getKeywords() ?: array(),
8650 'type' => $package->getType(),
8651 'homepage' => $package->getHomepage(),
8652 'names' => $package->getNames()
8653 );
8654
8655 $json = $this->appendVersions($json, $versions);
8656 $json = $this->appendLicenses($json, $package);
8657
8658 if ($latestPackage) {
8659 $json['latest'] = $latestPackage->getPrettyVersion();
8660 } else {
8661 $latestPackage = $package;
8662 }
8663
8664 if ($package->getSourceType()) {
8665 $json['source'] = array(
8666 'type' => $package->getSourceType(),
8667 'url' => $package->getSourceUrl(),
8668 'reference' => $package->getSourceReference()
8669 );
8670 }
8671
8672 if ($package->getDistType()) {
8673 $json['dist'] = array(
8674 'type' => $package->getDistType(),
8675 'url' => $package->getDistUrl(),
8676 'reference' => $package->getDistReference()
8677 );
8678 }
8679
8680 if ($installedRepo->hasPackage($package)) {
8681 $json['path'] = realpath($this->getComposer()->getInstallationManager()->getInstallPath($package));
8682 if ($json['path'] === false) {
8683 unset($json['path']);
8684 }
8685 }
8686
8687 if ($latestPackage->isAbandoned()) {
8688 $json['replacement'] = $latestPackage->getReplacementPackage();
8689 }
8690
8691 if ($package->getSuggests()) {
8692 $json['suggests'] = $package->getSuggests();
8693 }
8694
8695 if ($package->getSupport()) {
8696 $json['support'] = $package->getSupport();
8697 }
8698
8699 $json = $this->appendAutoload($json, $package);
8700
8701 if ($package->getIncludePaths()) {
8702 $json['include_path'] = $package->getIncludePaths();
8703 }
8704
8705 $json = $this->appendLinks($json, $package);
8706
8707 $this->getIO()->write(JsonFile::encode($json));
8708 }
8709
8710 private function appendVersions($json, array $versions)
8711 {
8712 uasort($versions, 'version_compare');
8713 $versions = array_keys(array_reverse($versions));
8714 $json['versions'] = $versions;
8715
8716 return $json;
8717 }
8718
8719 private function appendLicenses($json, CompletePackageInterface $package)
8720 {
8721 if ($licenses = $package->getLicense()) {
8722 $spdxLicenses = new SpdxLicenses();
8723
8724 $json['licenses'] = array_map(function ($licenseId) use ($spdxLicenses) {
8725 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
8726
8727 if (!$license) {
8728 return $licenseId;
8729 }
8730
8731 return array(
8732 'name' => $license[0],
8733 'osi' => $licenseId,
8734 'url' => $license[2]
8735 );
8736 }, $licenses);
8737 }
8738
8739 return $json;
8740 }
8741
8742 private function appendAutoload($json, CompletePackageInterface $package)
8743 {
8744 if ($package->getAutoload()) {
8745 $autoload = array();
8746
8747 foreach ($package->getAutoload() as $type => $autoloads) {
8748 if ($type === 'psr-0' || $type === 'psr-4') {
8749 $psr = array();
8750
8751 foreach ($autoloads as $name => $path) {
8752 if (!$path) {
8753 $path = '.';
8754 }
8755
8756 $psr[$name ?: '*'] = $path;
8757 }
8758
8759 $autoload[$type] = $psr;
8760 } elseif ($type === 'classmap') {
8761 $autoload['classmap'] = $autoloads;
8762 }
8763 }
8764
8765 $json['autoload'] = $autoload;
8766 }
8767
8768 return $json;
8769 }
8770
8771 private function appendLinks($json, CompletePackageInterface $package)
8772 {
8773 foreach (array('requires', 'devRequires', 'provides', 'conflicts', 'replaces') as $linkType) {
8774 $json = $this->appendLink($json, $package, $linkType);
8775 }
8776
8777 return $json;
8778 }
8779
8780 private function appendLink($json, CompletePackageInterface $package, $linkType)
8781 {
8782 $links = $package->{'get' . ucfirst($linkType)}();
8783
8784 if ($links) {
8785 $json[$linkType] = array();
8786
8787 foreach ($links as $link) {
8788 $json[$linkType][$link->getTarget()] = $link->getPrettyConstraint();
8789 }
8790 }
8791
8792 return $json;
8793 }
8794
8795
8796
8797
8798
8799
8800 protected function initStyles(OutputInterface $output)
8801 {
8802 $this->colors = array(
8803 'green',
8804 'yellow',
8805 'cyan',
8806 'magenta',
8807 'blue',
8808 );
8809
8810 foreach ($this->colors as $color) {
8811 $style = new OutputFormatterStyle($color);
8812 $output->getFormatter()->setStyle($color, $style);
8813 }
8814 }
8815
8816
8817
8818
8819
8820
8821 protected function displayPackageTree(array $arrayTree)
8822 {
8823 $io = $this->getIO();
8824 foreach ($arrayTree as $package) {
8825 $io->write(sprintf('<info>%s</info>', $package['name']), false);
8826 $io->write(' ' . $package['version'], false);
8827 $io->write(' ' . strtok($package['description'], "\r\n"));
8828
8829 if (isset($package['requires'])) {
8830 $requires = $package['requires'];
8831 $treeBar = '├';
8832 $j = 0;
8833 $total = count($requires);
8834 foreach ($requires as $require) {
8835 $requireName = $require['name'];
8836 $j++;
8837 if ($j === $total) {
8838 $treeBar = '└';
8839 }
8840 $level = 1;
8841 $color = $this->colors[$level];
8842 $info = sprintf(
8843 '%s──<%s>%s</%s> %s',
8844 $treeBar,
8845 $color,
8846 $requireName,
8847 $color,
8848 $require['version']
8849 );
8850 $this->writeTreeLine($info);
8851
8852 $treeBar = str_replace('└', ' ', $treeBar);
8853 $packagesInTree = array($package['name'], $requireName);
8854
8855 $this->displayTree($require, $packagesInTree, $treeBar, $level + 1);
8856 }
8857 }
8858 }
8859 }
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869 protected function generatePackageTree(
8870 PackageInterface $package,
8871 RepositoryInterface $installedRepo,
8872 RepositoryInterface $distantRepos
8873 ) {
8874 $requires = $package->getRequires();
8875 ksort($requires);
8876 $children = array();
8877 foreach ($requires as $requireName => $require) {
8878 $packagesInTree = array($package->getName(), $requireName);
8879
8880 $treeChildDesc = array(
8881 'name' => $requireName,
8882 'version' => $require->getPrettyConstraint(),
8883 );
8884
8885 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree);
8886
8887 if ($deepChildren) {
8888 $treeChildDesc['requires'] = $deepChildren;
8889 }
8890
8891 $children[] = $treeChildDesc;
8892 }
8893 $tree = array(
8894 'name' => $package->getPrettyName(),
8895 'version' => $package->getPrettyVersion(),
8896 'description' => $package->getDescription(),
8897 );
8898
8899 if ($children) {
8900 $tree['requires'] = $children;
8901 }
8902
8903 return $tree;
8904 }
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914 protected function displayTree(
8915 $package,
8916 array $packagesInTree,
8917 $previousTreeBar = '├',
8918 $level = 1
8919 ) {
8920 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
8921 if (isset($package['requires'])) {
8922 $requires = $package['requires'];
8923 $treeBar = $previousTreeBar . '  ├';
8924 $i = 0;
8925 $total = count($requires);
8926 foreach ($requires as $require) {
8927 $currentTree = $packagesInTree;
8928 $i++;
8929 if ($i === $total) {
8930 $treeBar = $previousTreeBar . '  └';
8931 }
8932 $colorIdent = $level % count($this->colors);
8933 $color = $this->colors[$colorIdent];
8934
8935 $circularWarn = in_array(
8936 $require['name'],
8937 $currentTree,
8938 true
8939 ) ? '(circular dependency aborted here)' : '';
8940 $info = rtrim(sprintf(
8941 '%s──<%s>%s</%s> %s %s',
8942 $treeBar,
8943 $color,
8944 $require['name'],
8945 $color,
8946 $require['version'],
8947 $circularWarn
8948 ));
8949 $this->writeTreeLine($info);
8950
8951 $treeBar = str_replace('└', ' ', $treeBar);
8952
8953 $currentTree[] = $require['name'];
8954 $this->displayTree($require, $currentTree, $treeBar, $level + 1);
8955 }
8956 }
8957 }
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969 protected function addTree(
8970 $name,
8971 $package,
8972 RepositoryInterface $installedRepo,
8973 RepositoryInterface $distantRepos,
8974 array $packagesInTree
8975 ) {
8976 $children = array();
8977 list($package, $versions) = $this->getPackage(
8978 $installedRepo,
8979 $distantRepos,
8980 $name,
8981 $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint()
8982 );
8983 if (is_object($package)) {
8984 $requires = $package->getRequires();
8985 ksort($requires);
8986 foreach ($requires as $requireName => $require) {
8987 $currentTree = $packagesInTree;
8988
8989 $treeChildDesc = array(
8990 'name' => $requireName,
8991 'version' => $require->getPrettyConstraint(),
8992 );
8993
8994 if (!in_array($requireName, $currentTree, true)) {
8995 $currentTree[] = $requireName;
8996 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $currentTree);
8997 if ($deepChildren) {
8998 $treeChildDesc['requires'] = $deepChildren;
8999 }
9000 }
9001
9002 $children[] = $treeChildDesc;
9003 }
9004 }
9005
9006 return $children;
9007 }
9008
9009 private function updateStatusToVersionStyle($updateStatus)
9010 {
9011
9012
9013
9014 return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
9015 }
9016
9017 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
9018 {
9019 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
9020 return 'up-to-date';
9021 }
9022
9023 $constraint = $package->getVersion();
9024 if (0 !== strpos($constraint, 'dev-')) {
9025 $constraint = '^'.$constraint;
9026 }
9027 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
9028
9029 return 'semver-safe-update';
9030 }
9031
9032
9033 return 'update-possible';
9034 }
9035
9036 private function writeTreeLine($line)
9037 {
9038 $io = $this->getIO();
9039 if (!$io->isDecorated()) {
9040 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
9041 }
9042
9043 $io->write($line);
9044 }
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
9057 {
9058
9059 $name = $package->getName();
9060 $versionSelector = new VersionSelector($this->getPool($composer));
9061 $stability = $composer->getPackage()->getMinimumStability();
9062 $flags = $composer->getPackage()->getStabilityFlags();
9063 if (isset($flags[$name])) {
9064 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
9065 }
9066
9067 $bestStability = $stability;
9068 if ($composer->getPackage()->getPreferStable()) {
9069 $bestStability = $package->getStability();
9070 }
9071
9072 $targetVersion = null;
9073 if (0 === strpos($package->getVersion(), 'dev-')) {
9074 $targetVersion = $package->getVersion();
9075 }
9076
9077 if ($targetVersion === null && $minorOnly) {
9078 $targetVersion = '^' . $package->getVersion();
9079 }
9080
9081 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
9082 }
9083
9084 private function getPool(Composer $composer)
9085 {
9086 if (!$this->pool) {
9087 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
9088 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
9089 }
9090
9091 return $this->pool;
9092 }
9093 }
9094 <?php
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106 namespace Composer\Command;
9107
9108 use Symfony\Component\Console\Input\InputInterface;
9109 use Symfony\Component\Console\Input\InputOption;
9110 use Symfony\Component\Console\Output\OutputInterface;
9111 use Composer\Downloader\ChangeReportInterface;
9112 use Composer\Downloader\DvcsDownloaderInterface;
9113 use Composer\Downloader\VcsCapableDownloaderInterface;
9114 use Composer\Package\Dumper\ArrayDumper;
9115 use Composer\Package\Version\VersionGuesser;
9116 use Composer\Package\Version\VersionParser;
9117 use Composer\Plugin\CommandEvent;
9118 use Composer\Plugin\PluginEvents;
9119 use Composer\Script\ScriptEvents;
9120 use Composer\Util\ProcessExecutor;
9121
9122
9123
9124
9125
9126 class StatusCommand extends BaseCommand
9127 {
9128 const EXIT_CODE_ERRORS = 1;
9129 const EXIT_CODE_UNPUSHED_CHANGES = 2;
9130 const EXIT_CODE_VERSION_CHANGES = 4;
9131
9132
9133
9134
9135 protected function configure()
9136 {
9137 $this
9138 ->setName('status')
9139 ->setDescription('Shows a list of locally modified packages.')
9140 ->setDefinition(array(
9141 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
9142 ))
9143 ->setHelp(
9144 <<<EOT
9145 The status command displays a list of dependencies that have
9146 been modified locally.
9147
9148 Read more at https://getcomposer.org/doc/03-cli.md#status
9149 EOT
9150 )
9151 ;
9152 }
9153
9154
9155
9156
9157
9158
9159 protected function execute(InputInterface $input, OutputInterface $output)
9160 {
9161 $composer = $this->getComposer();
9162
9163 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
9164 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
9165
9166
9167 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
9168
9169 $exitCode = $this->doExecute($input, $output);
9170
9171
9172 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
9173
9174 return $exitCode;
9175 }
9176
9177
9178
9179
9180
9181
9182 private function doExecute(InputInterface $input, OutputInterface $output)
9183 {
9184
9185 $composer = $this->getComposer();
9186
9187 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
9188
9189 $dm = $composer->getDownloadManager();
9190 $im = $composer->getInstallationManager();
9191
9192 $errors = array();
9193 $io = $this->getIO();
9194 $unpushedChanges = array();
9195 $vcsVersionChanges = array();
9196
9197 $parser = new VersionParser;
9198 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
9199 $dumper = new ArrayDumper;
9200
9201
9202 foreach ($installedRepo->getCanonicalPackages() as $package) {
9203 $downloader = $dm->getDownloaderForInstalledPackage($package);
9204 $targetDir = $im->getInstallPath($package);
9205
9206 if ($downloader instanceof ChangeReportInterface) {
9207 if (is_link($targetDir)) {
9208 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
9209 }
9210
9211 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
9212 $errors[$targetDir] = $changes;
9213 }
9214 }
9215
9216 if ($downloader instanceof VcsCapableDownloaderInterface) {
9217 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
9218 switch ($package->getInstallationSource()) {
9219 case 'source':
9220 $previousRef = $package->getSourceReference();
9221 break;
9222 case 'dist':
9223 $previousRef = $package->getDistReference();
9224 break;
9225 default:
9226 $previousRef = null;
9227 }
9228
9229 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
9230
9231 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
9232 $vcsVersionChanges[$targetDir] = array(
9233 'previous' => array(
9234 'version' => $package->getPrettyVersion(),
9235 'ref' => $previousRef,
9236 ),
9237 'current' => array(
9238 'version' => $currentVersion['pretty_version'],
9239 'ref' => $currentVersion['commit'],
9240 ),
9241 );
9242 }
9243 }
9244 }
9245
9246 if ($downloader instanceof DvcsDownloaderInterface) {
9247 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
9248 $unpushedChanges[$targetDir] = $unpushed;
9249 }
9250 }
9251 }
9252
9253
9254 if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
9255 $io->writeError('<info>No local changes</info>');
9256
9257 return 0;
9258 }
9259
9260 if ($errors) {
9261 $io->writeError('<error>You have changes in the following dependencies:</error>');
9262
9263 foreach ($errors as $path => $changes) {
9264 if ($input->getOption('verbose')) {
9265 $indentedChanges = implode("\n", array_map(function ($line) {
9266 return '    ' . ltrim($line);
9267 }, explode("\n", $changes)));
9268 $io->write('<info>'.$path.'</info>:');
9269 $io->write($indentedChanges);
9270 } else {
9271 $io->write($path);
9272 }
9273 }
9274 }
9275
9276 if ($unpushedChanges) {
9277 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
9278
9279 foreach ($unpushedChanges as $path => $changes) {
9280 if ($input->getOption('verbose')) {
9281 $indentedChanges = implode("\n", array_map(function ($line) {
9282 return '    ' . ltrim($line);
9283 }, explode("\n", $changes)));
9284 $io->write('<info>'.$path.'</info>:');
9285 $io->write($indentedChanges);
9286 } else {
9287 $io->write($path);
9288 }
9289 }
9290 }
9291
9292 if ($vcsVersionChanges) {
9293 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
9294
9295 foreach ($vcsVersionChanges as $path => $changes) {
9296 if ($input->getOption('verbose')) {
9297
9298 $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
9299 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
9300
9301 if ($io->isVeryVerbose()) {
9302
9303 $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
9304 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
9305 }
9306
9307 $io->write('<info>'.$path.'</info>:');
9308 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
9309 } else {
9310 $io->write($path);
9311 }
9312 }
9313 }
9314
9315 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
9316 $io->writeError('Use --verbose (-v) to see a list of files');
9317 }
9318
9319 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
9320 }
9321 }
9322 <?php
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334 namespace Composer\Command;
9335
9336 use Composer\Repository\PlatformRepository;
9337 use Symfony\Component\Console\Input\InputArgument;
9338 use Symfony\Component\Console\Input\InputInterface;
9339 use Symfony\Component\Console\Input\InputOption;
9340 use Symfony\Component\Console\Output\OutputInterface;
9341
9342 class SuggestsCommand extends BaseCommand
9343 {
9344 protected function configure()
9345 {
9346 $this
9347 ->setName('suggests')
9348 ->setDescription('Shows package suggestions.')
9349 ->setDefinition(array(
9350 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
9351 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
9352 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
9353 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
9354 ))
9355 ->setHelp(
9356 <<<EOT
9357
9358 The <info>%command.name%</info> command shows a sorted list of suggested packages.
9359
9360 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
9361
9362 Read more at https://getcomposer.org/doc/03-cli.md#suggests
9363 EOT
9364 )
9365 ;
9366 }
9367
9368 protected function execute(InputInterface $input, OutputInterface $output)
9369 {
9370 $lock = $this->getComposer()->getLocker()->getLockData();
9371
9372 if (empty($lock)) {
9373 throw new \RuntimeException('Lockfile seems to be empty?');
9374 }
9375
9376 $packages = $lock['packages'];
9377
9378 if (!$input->getOption('no-dev')) {
9379 $packages += $lock['packages-dev'];
9380 }
9381
9382 $filter = $input->getArgument('packages');
9383
9384
9385 $installed = array();
9386 foreach ($packages as $package) {
9387 $installed[] = $package['name'];
9388
9389 if (!empty($package['provide'])) {
9390 $installed = array_merge($installed, array_keys($package['provide']));
9391 }
9392
9393 if (!empty($package['replace'])) {
9394 $installed = array_merge($installed, array_keys($package['replace']));
9395 }
9396 }
9397
9398
9399 $installed = array_flip($installed);
9400 ksort($installed);
9401
9402
9403 $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
9404
9405
9406 $suggesters = array();
9407 $suggested = array();
9408 foreach ($packages as $package) {
9409 $packageName = $package['name'];
9410 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
9411 continue;
9412 }
9413 foreach ($package['suggest'] as $suggestion => $reason) {
9414 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
9415 continue;
9416 }
9417 if (!isset($installed[$suggestion])) {
9418 $suggesters[$packageName][$suggestion] = $reason;
9419 $suggested[$suggestion][$packageName] = $reason;
9420 }
9421 }
9422 }
9423 ksort($suggesters);
9424 ksort($suggested);
9425
9426
9427 $mode = 0;
9428 $io = $this->getIO();
9429 if ($input->getOption('by-package') || $io->isVerbose()) {
9430 $mode |= 1;
9431 }
9432 if ($input->getOption('by-suggestion')) {
9433 $mode |= 2;
9434 }
9435
9436
9437 if ($mode === 0) {
9438 foreach (array_keys($suggested) as $suggestion) {
9439 $io->write(sprintf('<info>%s</info>', $suggestion));
9440 }
9441
9442 return 0;
9443 }
9444
9445
9446 if ($mode & 1) {
9447 foreach ($suggesters as $suggester => $suggestions) {
9448 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
9449
9450 foreach ($suggestions as $suggestion => $reason) {
9451 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
9452 }
9453 $io->write('');
9454 }
9455 }
9456
9457
9458 if ($mode & 2) {
9459
9460 if ($mode & 1) {
9461 $io->write(str_repeat('-', 78));
9462 }
9463 foreach ($suggested as $suggestion => $suggesters) {
9464 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
9465
9466 foreach ($suggesters as $suggester => $reason) {
9467 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
9468 }
9469 $io->write('');
9470 }
9471 }
9472
9473 return 0;
9474 }
9475 }
9476 <?php
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488 namespace Composer\Command;
9489
9490 use Composer\Composer;
9491 use Composer\Installer;
9492 use Composer\IO\IOInterface;
9493 use Composer\Plugin\CommandEvent;
9494 use Composer\Plugin\PluginEvents;
9495 use Symfony\Component\Console\Helper\Table;
9496 use Symfony\Component\Console\Input\InputInterface;
9497 use Symfony\Component\Console\Input\InputOption;
9498 use Symfony\Component\Console\Input\InputArgument;
9499 use Symfony\Component\Console\Output\OutputInterface;
9500 use Symfony\Component\Console\Question\Question;
9501
9502
9503
9504
9505
9506 class UpdateCommand extends BaseCommand
9507 {
9508 protected function configure()
9509 {
9510 $this
9511 ->setName('update')
9512 ->setAliases(array('u', 'upgrade'))
9513 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
9514 ->setDefinition(array(
9515 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
9516 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
9517 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
9518 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
9519 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
9520 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
9521 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
9522 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
9523 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
9524 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
9525 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
9526 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
9527 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of allowed packages to the allow list, except those defined in root package.'),
9528 new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of allowed packages to the allow list, including those defined in root package.'),
9529 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
9530 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
9531 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
9532 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
9533 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
9534 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
9535 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
9536 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
9537 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
9538 ))
9539 ->setHelp(
9540 <<<EOT
9541 The <info>update</info> command reads the composer.json file from the
9542 current directory, processes it, and updates, removes or installs all the
9543 dependencies.
9544
9545 <info>php composer.phar update</info>
9546
9547 To limit the update operation to a few packages, you can list the package(s)
9548 you want to update as such:
9549
9550 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
9551
9552 You may also use an asterisk (*) pattern to limit the update operation to package(s)
9553 from a specific vendor:
9554
9555 <info>php composer.phar update vendor/package1 foo/* [...]</info>
9556
9557 To select packages names interactively with auto-completion use <info>-i</info>.
9558
9559 Read more at https://getcomposer.org/doc/03-cli.md#update-u
9560 EOT
9561 )
9562 ;
9563 }
9564
9565 protected function execute(InputInterface $input, OutputInterface $output)
9566 {
9567 $io = $this->getIO();
9568 if ($input->getOption('no-custom-installers')) {
9569 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
9570 $input->setOption('no-plugins', true);
9571 }
9572
9573 if ($input->getOption('dev')) {
9574 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
9575 }
9576
9577 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
9578
9579 $packages = $input->getArgument('packages');
9580
9581 if ($input->getOption('interactive')) {
9582 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
9583 }
9584
9585 if ($input->getOption('root-reqs')) {
9586 $require = array_keys($composer->getPackage()->getRequires());
9587 if (!$input->getOption('no-dev')) {
9588 $requireDev = array_keys($composer->getPackage()->getDevRequires());
9589 $require = array_merge($require, $requireDev);
9590 }
9591
9592 if (!empty($packages)) {
9593 $packages = array_intersect($packages, $require);
9594 } else {
9595 $packages = $require;
9596 }
9597 }
9598
9599 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
9600
9601 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
9602 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
9603
9604 $install = Installer::create($io, $composer);
9605
9606 $config = $composer->getConfig();
9607 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
9608
9609 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
9610 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
9611 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
9612
9613 $install
9614 ->setDryRun($input->getOption('dry-run'))
9615 ->setVerbose($input->getOption('verbose'))
9616 ->setPreferSource($preferSource)
9617 ->setPreferDist($preferDist)
9618 ->setDevMode(!$input->getOption('no-dev'))
9619 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
9620 ->setRunScripts(!$input->getOption('no-scripts'))
9621 ->setSkipSuggest($input->getOption('no-suggest'))
9622 ->setOptimizeAutoloader($optimize)
9623 ->setClassMapAuthoritative($authoritative)
9624 ->setApcuAutoloader($apcu)
9625 ->setUpdate(true)
9626 ->setUpdateAllowList($input->getOption('lock') ? array('lock') : $packages)
9627 ->setAllowListTransitiveDependencies($input->getOption('with-dependencies'))
9628 ->setAllowListAllDependencies($input->getOption('with-all-dependencies'))
9629 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
9630 ->setPreferStable($input->getOption('prefer-stable'))
9631 ->setPreferLowest($input->getOption('prefer-lowest'))
9632 ;
9633
9634 if ($input->getOption('no-plugins')) {
9635 $install->disablePlugins();
9636 }
9637
9638 return $install->run();
9639 }
9640
9641 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
9642 {
9643 if (!$input->isInteractive()) {
9644 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
9645 }
9646
9647 $requires = array_merge(
9648 $composer->getPackage()->getRequires(),
9649 $composer->getPackage()->getDevRequires()
9650 );
9651 $autocompleterValues = array();
9652 foreach ($requires as $require) {
9653 $target = $require->getTarget();
9654 $autocompleterValues[strtolower($target)] = $target;
9655 }
9656
9657 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
9658 foreach ($installedPackages as $package) {
9659 $autocompleterValues[$package->getName()] = $package->getPrettyName();
9660 }
9661
9662 $helper = $this->getHelper('question');
9663 $question = new Question('<comment>Enter package name: </comment>', null);
9664
9665 $io->writeError('<info>Press enter without value to end submission</info>');
9666
9667 do {
9668 $autocompleterValues = array_diff($autocompleterValues, $packages);
9669 $question->setAutocompleterValues($autocompleterValues);
9670 $addedPackage = $helper->ask($input, $output, $question);
9671
9672 if (!is_string($addedPackage) || empty($addedPackage)) {
9673 break;
9674 }
9675
9676 $addedPackage = strtolower($addedPackage);
9677 if (!in_array($addedPackage, $packages)) {
9678 $packages[] = $addedPackage;
9679 }
9680 } while (true);
9681
9682 $packages = array_filter($packages);
9683 if (!$packages) {
9684 throw new \InvalidArgumentException('You must enter minimum one package.');
9685 }
9686
9687 $table = new Table($output);
9688 $table->setHeaders(array('Selected packages'));
9689 foreach ($packages as $package) {
9690 $table->addRow(array($package));
9691 }
9692 $table->render();
9693
9694 if ($io->askConfirmation(sprintf(
9695 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
9696 1 === count($packages) ? '' : 's'
9697 ), true)) {
9698 return $packages;
9699 }
9700
9701 throw new \RuntimeException('Installation aborted.');
9702 }
9703 }
9704 <?php
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716 namespace Composer\Command;
9717
9718 use Composer\Factory;
9719 use Composer\Package\Loader\ValidatingArrayLoader;
9720 use Composer\Plugin\CommandEvent;
9721 use Composer\Plugin\PluginEvents;
9722 use Composer\Util\ConfigValidator;
9723 use Symfony\Component\Console\Input\InputArgument;
9724 use Symfony\Component\Console\Input\InputInterface;
9725 use Symfony\Component\Console\Input\InputOption;
9726 use Symfony\Component\Console\Output\OutputInterface;
9727
9728
9729
9730
9731
9732
9733
9734 class ValidateCommand extends BaseCommand
9735 {
9736
9737
9738
9739 protected function configure()
9740 {
9741 $this
9742 ->setName('validate')
9743 ->setDescription('Validates a composer.json and composer.lock.')
9744 ->setDefinition(array(
9745 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not validate requires for overly strict/loose constraints'),
9746 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
9747 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
9748 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
9749 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
9750 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
9751 ))
9752 ->setHelp(
9753 <<<EOT
9754 The validate command validates a given composer.json and composer.lock
9755
9756 Exit codes in case of errors are:
9757 1 validation warning(s), only when --strict is given
9758 2 validation error(s)
9759 3 file unreadable or missing
9760
9761 Read more at https://getcomposer.org/doc/03-cli.md#validate
9762 EOT
9763 );
9764 }
9765
9766
9767
9768
9769
9770
9771
9772 protected function execute(InputInterface $input, OutputInterface $output)
9773 {
9774 $file = $input->getArgument('file') ?: Factory::getComposerFile();
9775 $io = $this->getIO();
9776
9777 if (!file_exists($file)) {
9778 $io->writeError('<error>' . $file . ' not found.</error>');
9779
9780 return 3;
9781 }
9782 if (!is_readable($file)) {
9783 $io->writeError('<error>' . $file . ' is not readable.</error>');
9784
9785 return 3;
9786 }
9787
9788 $validator = new ConfigValidator($io);
9789 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
9790 $checkPublish = !$input->getOption('no-check-publish');
9791 $checkLock = !$input->getOption('no-check-lock');
9792 $isStrict = $input->getOption('strict');
9793 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
9794
9795 $lockErrors = array();
9796 $composer = Factory::create($io, $file, $input->hasParameterOption('--no-plugins'));
9797 $locker = $composer->getLocker();
9798 if ($locker->isLocked() && !$locker->isFresh()) {
9799 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update` or `composer update <package name>`.';
9800 }
9801
9802 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
9803
9804
9805 $exitCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
9806
9807 if ($input->getOption('with-dependencies')) {
9808 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
9809 foreach ($localRepo->getPackages() as $package) {
9810 $path = $composer->getInstallationManager()->getInstallPath($package);
9811 $file = $path . '/composer.json';
9812 if (is_dir($path) && file_exists($file)) {
9813 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
9814
9815 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
9816
9817
9818 $depCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
9819 $exitCode = max($depCode, $exitCode);
9820 }
9821 }
9822 }
9823
9824 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
9825 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
9826 $exitCode = max($eventCode, $exitCode);
9827
9828 return $exitCode;
9829 }
9830
9831 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
9832 {
9833 $doPrintSchemaUrl = false;
9834
9835 if ($errors) {
9836 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
9837 } elseif ($publishErrors) {
9838 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
9839 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
9840 $doPrintSchemaUrl = $printSchemaUrl;
9841 } elseif ($warnings) {
9842 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
9843 $doPrintSchemaUrl = $printSchemaUrl;
9844 } else {
9845 $io->write('<info>' . $name . ' is valid</info>');
9846
9847 }
9848
9849 if ($doPrintSchemaUrl) {
9850 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
9851 }
9852
9853
9854 $extraWarnings = array();
9855
9856
9857 if ($checkPublish) {
9858 $errors = array_merge($errors, $publishErrors);
9859 } else {
9860 $extraWarnings = array_merge($extraWarnings, $publishErrors);
9861 }
9862
9863
9864 if ($checkLock) {
9865 $errors = array_merge($errors, $lockErrors);
9866 } else {
9867 $extraWarnings = array_merge($extraWarnings, $lockErrors);
9868 }
9869
9870 $messages = array(
9871 'error' => $errors,
9872 'warning' => array_merge($warnings, $extraWarnings),
9873 );
9874
9875 foreach ($messages as $style => $msgs) {
9876 foreach ($msgs as $msg) {
9877 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
9878 }
9879 }
9880 }
9881 }
9882 <?php
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894 namespace Composer;
9895
9896 use Composer\Package\RootPackageInterface;
9897 use Composer\Package\Locker;
9898 use Composer\Repository\RepositoryManager;
9899 use Composer\Installer\InstallationManager;
9900 use Composer\Plugin\PluginManager;
9901 use Composer\Downloader\DownloadManager;
9902 use Composer\EventDispatcher\EventDispatcher;
9903 use Composer\Autoload\AutoloadGenerator;
9904 use Composer\Package\Archiver\ArchiveManager;
9905
9906
9907
9908
9909
9910
9911 class Composer
9912 {
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934 const VERSION = '1.10.26';
9935 const BRANCH_ALIAS_VERSION = '';
9936 const RELEASE_DATE = '2022-04-13 16:39:56';
9937 const SOURCE_VERSION = '';
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948 const RUNTIME_API_VERSION = '1.0.0';
9949
9950 public static function getVersion()
9951 {
9952
9953 if (self::VERSION === '@package_version'.'@') {
9954 return self::SOURCE_VERSION;
9955 }
9956
9957
9958 if (self::BRANCH_ALIAS_VERSION !== '' && preg_match('{^[a-f0-9]{40}$}', self::VERSION)) {
9959 return self::BRANCH_ALIAS_VERSION.'+'.self::VERSION;
9960 }
9961
9962 return self::VERSION;
9963 }
9964
9965
9966
9967
9968 private $package;
9969
9970
9971
9972
9973 private $locker;
9974
9975
9976
9977
9978 private $repositoryManager;
9979
9980
9981
9982
9983 private $downloadManager;
9984
9985
9986
9987
9988 private $installationManager;
9989
9990
9991
9992
9993 private $pluginManager;
9994
9995
9996
9997
9998 private $config;
9999
10000
10001
10002
10003 private $eventDispatcher;
10004
10005
10006
10007
10008 private $autoloadGenerator;
10009
10010
10011
10012
10013 private $archiveManager;
10014
10015
10016
10017
10018
10019 public function setPackage(RootPackageInterface $package)
10020 {
10021 $this->package = $package;
10022 }
10023
10024
10025
10026
10027 public function getPackage()
10028 {
10029 return $this->package;
10030 }
10031
10032
10033
10034
10035 public function setConfig(Config $config)
10036 {
10037 $this->config = $config;
10038 }
10039
10040
10041
10042
10043 public function getConfig()
10044 {
10045 return $this->config;
10046 }
10047
10048
10049
10050
10051 public function setLocker(Locker $locker)
10052 {
10053 $this->locker = $locker;
10054 }
10055
10056
10057
10058
10059 public function getLocker()
10060 {
10061 return $this->locker;
10062 }
10063
10064
10065
10066
10067 public function setRepositoryManager(RepositoryManager $manager)
10068 {
10069 $this->repositoryManager = $manager;
10070 }
10071
10072
10073
10074
10075 public function getRepositoryManager()
10076 {
10077 return $this->repositoryManager;
10078 }
10079
10080
10081
10082
10083 public function setDownloadManager(DownloadManager $manager)
10084 {
10085 $this->downloadManager = $manager;
10086 }
10087
10088
10089
10090
10091 public function getDownloadManager()
10092 {
10093 return $this->downloadManager;
10094 }
10095
10096
10097
10098
10099 public function setArchiveManager(ArchiveManager $manager)
10100 {
10101 $this->archiveManager = $manager;
10102 }
10103
10104
10105
10106
10107 public function getArchiveManager()
10108 {
10109 return $this->archiveManager;
10110 }
10111
10112
10113
10114
10115 public function setInstallationManager(InstallationManager $manager)
10116 {
10117 $this->installationManager = $manager;
10118 }
10119
10120
10121
10122
10123 public function getInstallationManager()
10124 {
10125 return $this->installationManager;
10126 }
10127
10128
10129
10130
10131 public function setPluginManager(PluginManager $manager)
10132 {
10133 $this->pluginManager = $manager;
10134 }
10135
10136
10137
10138
10139 public function getPluginManager()
10140 {
10141 return $this->pluginManager;
10142 }
10143
10144
10145
10146
10147 public function setEventDispatcher(EventDispatcher $eventDispatcher)
10148 {
10149 $this->eventDispatcher = $eventDispatcher;
10150 }
10151
10152
10153
10154
10155 public function getEventDispatcher()
10156 {
10157 return $this->eventDispatcher;
10158 }
10159
10160
10161
10162
10163 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
10164 {
10165 $this->autoloadGenerator = $autoloadGenerator;
10166 }
10167
10168
10169
10170
10171 public function getAutoloadGenerator()
10172 {
10173 return $this->autoloadGenerator;
10174 }
10175 }
10176 <?php
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188 namespace Composer;
10189
10190 use Composer\Config\ConfigSourceInterface;
10191 use Composer\Downloader\TransportException;
10192 use Composer\IO\IOInterface;
10193 use Composer\Util\Platform;
10194 use Composer\Util\ProcessExecutor;
10195
10196
10197
10198
10199 class Config
10200 {
10201 const RELATIVE_PATHS = 1;
10202
10203 public static $defaultConfig = array(
10204 'process-timeout' => 300,
10205 'use-include-path' => false,
10206 'preferred-install' => 'auto',
10207 'notify-on-install' => true,
10208 'github-protocols' => array('https', 'ssh', 'git'),
10209 'vendor-dir' => 'vendor',
10210 'bin-dir' => '{$vendor-dir}/bin',
10211 'cache-dir' => '{$home}/cache',
10212 'data-dir' => '{$home}',
10213 'cache-files-dir' => '{$cache-dir}/files',
10214 'cache-repo-dir' => '{$cache-dir}/repo',
10215 'cache-vcs-dir' => '{$cache-dir}/vcs',
10216 'cache-ttl' => 15552000, 
10217 'cache-files-ttl' => null, 
10218 'cache-files-maxsize' => '300MiB',
10219 'bin-compat' => 'auto',
10220 'discard-changes' => false,
10221 'autoloader-suffix' => null,
10222 'sort-packages' => false,
10223 'optimize-autoloader' => false,
10224 'classmap-authoritative' => false,
10225 'apcu-autoloader' => false,
10226 'prepend-autoloader' => true,
10227 'github-domains' => array('github.com'),
10228 'bitbucket-expose-hostname' => true,
10229 'disable-tls' => false,
10230 'secure-http' => true,
10231 'cafile' => null,
10232 'capath' => null,
10233 'github-expose-hostname' => true,
10234 'gitlab-domains' => array('gitlab.com'),
10235 'store-auths' => 'prompt',
10236 'platform' => array(),
10237 'archive-format' => 'tar',
10238 'archive-dir' => '.',
10239 'htaccess-protect' => true,
10240 'use-github-api' => true,
10241 'lock' => true,
10242
10243
10244
10245
10246
10247
10248
10249 );
10250
10251 public static $defaultRepositories = array(
10252 'packagist.org' => array(
10253 'type' => 'composer',
10254 'url' => 'https?://repo.packagist.org',
10255 'allow_ssl_downgrade' => true,
10256 ),
10257 );
10258
10259 private $config;
10260 private $baseDir;
10261 private $repositories;
10262
10263 private $configSource;
10264
10265 private $authConfigSource;
10266 private $useEnvironment;
10267 private $warnedHosts = array();
10268
10269
10270
10271
10272
10273 public function __construct($useEnvironment = true, $baseDir = null)
10274 {
10275
10276 $this->config = static::$defaultConfig;
10277 $this->repositories = static::$defaultRepositories;
10278 $this->useEnvironment = (bool) $useEnvironment;
10279 $this->baseDir = $baseDir;
10280 }
10281
10282 public function setConfigSource(ConfigSourceInterface $source)
10283 {
10284 $this->configSource = $source;
10285 }
10286
10287 public function getConfigSource()
10288 {
10289 return $this->configSource;
10290 }
10291
10292 public function setAuthConfigSource(ConfigSourceInterface $source)
10293 {
10294 $this->authConfigSource = $source;
10295 }
10296
10297 public function getAuthConfigSource()
10298 {
10299 return $this->authConfigSource;
10300 }
10301
10302
10303
10304
10305
10306
10307 public function merge($config)
10308 {
10309
10310 if (!empty($config['config']) && is_array($config['config'])) {
10311 foreach ($config['config'] as $key => $val) {
10312 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic', 'bearer')) && isset($this->config[$key])) {
10313 $this->config[$key] = array_merge($this->config[$key], $val);
10314 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
10315 if (is_array($val) || is_array($this->config[$key])) {
10316 if (is_string($val)) {
10317 $val = array('*' => $val);
10318 }
10319 if (is_string($this->config[$key])) {
10320 $this->config[$key] = array('*' => $this->config[$key]);
10321 }
10322 $this->config[$key] = array_merge($this->config[$key], $val);
10323
10324 if (isset($this->config[$key]['*'])) {
10325 $wildcard = $this->config[$key]['*'];
10326 unset($this->config[$key]['*']);
10327 $this->config[$key]['*'] = $wildcard;
10328 }
10329 } else {
10330 $this->config[$key] = $val;
10331 }
10332 } else {
10333 $this->config[$key] = $val;
10334 }
10335 }
10336 }
10337
10338 if (!empty($config['repositories']) && is_array($config['repositories'])) {
10339 $this->repositories = array_reverse($this->repositories, true);
10340 $newRepos = array_reverse($config['repositories'], true);
10341 foreach ($newRepos as $name => $repository) {
10342
10343 if (false === $repository) {
10344 $this->disableRepoByName($name);
10345 continue;
10346 }
10347
10348
10349 if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
10350 $this->disableRepoByName(key($repository));
10351 continue;
10352 }
10353
10354
10355 if (is_int($name)) {
10356 $this->repositories[] = $repository;
10357 } else {
10358 if ($name === 'packagist') { 
10359 $this->repositories[$name . '.org'] = $repository;
10360 } else {
10361 $this->repositories[$name] = $repository;
10362 }
10363 }
10364 }
10365 $this->repositories = array_reverse($this->repositories, true);
10366 }
10367 }
10368
10369
10370
10371
10372 public function getRepositories()
10373 {
10374 return $this->repositories;
10375 }
10376
10377
10378
10379
10380
10381
10382
10383
10384
10385 public function get($key, $flags = 0)
10386 {
10387 switch ($key) {
10388 case 'vendor-dir':
10389 case 'bin-dir':
10390 case 'process-timeout':
10391 case 'data-dir':
10392 case 'cache-dir':
10393 case 'cache-files-dir':
10394 case 'cache-repo-dir':
10395 case 'cache-vcs-dir':
10396 case 'cafile':
10397 case 'capath':
10398
10399 $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
10400
10401 $val = $this->getComposerEnv($env);
10402 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
10403 $val = Platform::expandPath($val);
10404
10405 if (substr($key, -4) !== '-dir') {
10406 return $val;
10407 }
10408
10409 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
10410
10411 case 'htaccess-protect':
10412 $value = $this->getComposerEnv('COMPOSER_HTACCESS_PROTECT');
10413 if (false === $value) {
10414 $value = $this->config[$key];
10415 }
10416 return $value !== 'false' && (bool) $value;
10417
10418 case 'cache-ttl':
10419 return (int) $this->config[$key];
10420
10421 case 'cache-files-maxsize':
10422 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
10423 throw new \RuntimeException(
10424 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
10425 );
10426 }
10427 $size = $matches[1];
10428 if (isset($matches[2])) {
10429 switch (strtolower($matches[2])) {
10430 case 'g':
10431 $size *= 1024;
10432
10433
10434 case 'm':
10435 $size *= 1024;
10436
10437
10438 case 'k':
10439 $size *= 1024;
10440 break;
10441 }
10442 }
10443
10444 return $size;
10445
10446 case 'cache-files-ttl':
10447 if (isset($this->config[$key])) {
10448 return (int) $this->config[$key];
10449 }
10450
10451 return (int) $this->config['cache-ttl'];
10452
10453 case 'home':
10454 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
10455
10456 return rtrim($this->process($val, $flags), '/\\');
10457
10458 case 'bin-compat':
10459 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
10460
10461 if (!in_array($value, array('auto', 'full'))) {
10462 throw new \RuntimeException(
10463 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
10464 );
10465 }
10466
10467 return $value;
10468
10469 case 'discard-changes':
10470 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
10471 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
10472 throw new \RuntimeException(
10473 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
10474 );
10475 }
10476 if ('stash' === $env) {
10477 return 'stash';
10478 }
10479
10480
10481 return $env !== 'false' && (bool) $env;
10482 }
10483
10484 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
10485 throw new \RuntimeException(
10486 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
10487 );
10488 }
10489
10490 return $this->config[$key];
10491
10492 case 'github-protocols':
10493 $protos = $this->config['github-protocols'];
10494 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
10495 unset($protos[$index]);
10496 }
10497 if (reset($protos) === 'http') {
10498 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
10499 }
10500
10501 return $protos;
10502
10503 case 'disable-tls':
10504 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10505 case 'secure-http':
10506 if ($this->get('disable-tls') === true) {
10507 return false;
10508 }
10509
10510 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10511 case 'use-github-api':
10512 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10513 case 'lock':
10514 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10515 default:
10516 if (!isset($this->config[$key])) {
10517 return null;
10518 }
10519
10520 return $this->process($this->config[$key], $flags);
10521 }
10522 }
10523
10524 public function all($flags = 0)
10525 {
10526 $all = array(
10527 'repositories' => $this->getRepositories(),
10528 );
10529 foreach (array_keys($this->config) as $key) {
10530 $all['config'][$key] = $this->get($key, $flags);
10531 }
10532
10533 return $all;
10534 }
10535
10536 public function raw()
10537 {
10538 return array(
10539 'repositories' => $this->getRepositories(),
10540 'config' => $this->config,
10541 );
10542 }
10543
10544
10545
10546
10547
10548
10549
10550 public function has($key)
10551 {
10552 return array_key_exists($key, $this->config);
10553 }
10554
10555
10556
10557
10558
10559
10560
10561
10562 private function process($value, $flags)
10563 {
10564 $config = $this;
10565
10566 if (!is_string($value)) {
10567 return $value;
10568 }
10569
10570 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
10571 return $config->get($match[1], $flags);
10572 }, $value);
10573 }
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583 private function realpath($path)
10584 {
10585 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
10586 return $path;
10587 }
10588
10589 return $this->baseDir . '/' . $path;
10590 }
10591
10592
10593
10594
10595
10596
10597
10598
10599
10600
10601 private function getComposerEnv($var)
10602 {
10603 if ($this->useEnvironment) {
10604 return getenv($var);
10605 }
10606
10607 return false;
10608 }
10609
10610 private function disableRepoByName($name)
10611 {
10612 if (isset($this->repositories[$name])) {
10613 unset($this->repositories[$name]);
10614 } elseif ($name === 'packagist') { 
10615 unset($this->repositories['packagist.org']);
10616 }
10617 }
10618
10619
10620
10621
10622
10623
10624
10625 public function prohibitUrlByConfig($url, IOInterface $io = null)
10626 {
10627
10628 if (false === filter_var($url, FILTER_VALIDATE_URL)) {
10629 return;
10630 }
10631
10632
10633 $scheme = parse_url($url, PHP_URL_SCHEME);
10634 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
10635 if ($this->get('secure-http')) {
10636 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
10637 } elseif ($io) {
10638 $host = parse_url($url, PHP_URL_HOST);
10639 if (!isset($this->warnedHosts[$host])) {
10640 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
10641 }
10642 $this->warnedHosts[$host] = true;
10643 }
10644 }
10645 }
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656
10657 public static function disableProcessTimeout()
10658 {
10659
10660 ProcessExecutor::setTimeout(0);
10661 }
10662 }
10663 <?php
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675 namespace Composer\Config;
10676
10677
10678
10679
10680
10681
10682
10683 interface ConfigSourceInterface
10684 {
10685
10686
10687
10688
10689
10690
10691 public function addRepository($name, $config);
10692
10693
10694
10695
10696
10697
10698 public function removeRepository($name);
10699
10700
10701
10702
10703
10704
10705
10706 public function addConfigSetting($name, $value);
10707
10708
10709
10710
10711
10712
10713 public function removeConfigSetting($name);
10714
10715
10716
10717
10718
10719
10720
10721 public function addProperty($name, $value);
10722
10723
10724
10725
10726
10727
10728 public function removeProperty($name);
10729
10730
10731
10732
10733
10734
10735
10736
10737 public function addLink($type, $name, $value);
10738
10739
10740
10741
10742
10743
10744
10745 public function removeLink($type, $name);
10746
10747
10748
10749
10750
10751
10752 public function getName();
10753 }
10754 <?php
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765
10766 namespace Composer\Config;
10767
10768 use Composer\Json\JsonFile;
10769 use Composer\Json\JsonManipulator;
10770 use Composer\Util\Silencer;
10771
10772
10773
10774
10775
10776
10777
10778 class JsonConfigSource implements ConfigSourceInterface
10779 {
10780
10781
10782
10783 private $file;
10784
10785
10786
10787
10788 private $authConfig;
10789
10790
10791
10792
10793
10794
10795
10796 public function __construct(JsonFile $file, $authConfig = false)
10797 {
10798 $this->file = $file;
10799 $this->authConfig = $authConfig;
10800 }
10801
10802
10803
10804
10805 public function getName()
10806 {
10807 return $this->file->getPath();
10808 }
10809
10810
10811
10812
10813 public function addRepository($name, $config)
10814 {
10815 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
10816
10817
10818 if (isset($config['repositories'])) {
10819 foreach ($config['repositories'] as $index => $val) {
10820 if ($index === $repo) {
10821 continue;
10822 }
10823 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
10824 unset($config['repositories'][$index]);
10825 $config['repositories']['packagist.org'] = false;
10826 break;
10827 }
10828 }
10829 }
10830
10831 $config['repositories'][$repo] = $repoConfig;
10832 });
10833 }
10834
10835
10836
10837
10838 public function removeRepository($name)
10839 {
10840 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
10841 unset($config['repositories'][$repo]);
10842 });
10843 }
10844
10845
10846
10847
10848 public function addConfigSetting($name, $value)
10849 {
10850 $authConfig = $this->authConfig;
10851 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
10852 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) {
10853 list($key, $host) = explode('.', $key, 2);
10854 if ($authConfig) {
10855 $config[$key][$host] = $val;
10856 } else {
10857 $config['config'][$key][$host] = $val;
10858 }
10859 } else {
10860 $config['config'][$key] = $val;
10861 }
10862 });
10863 }
10864
10865
10866
10867
10868 public function removeConfigSetting($name)
10869 {
10870 $authConfig = $this->authConfig;
10871 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
10872 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) {
10873 list($key, $host) = explode('.', $key, 2);
10874 if ($authConfig) {
10875 unset($config[$key][$host]);
10876 } else {
10877 unset($config['config'][$key][$host]);
10878 }
10879 } else {
10880 unset($config['config'][$key]);
10881 }
10882 });
10883 }
10884
10885
10886
10887
10888 public function addProperty($name, $value)
10889 {
10890 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
10891 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10892 $bits = explode('.', $key);
10893 $last = array_pop($bits);
10894 $arr = &$config[reset($bits)];
10895 foreach ($bits as $bit) {
10896 if (!isset($arr[$bit])) {
10897 $arr[$bit] = array();
10898 }
10899 $arr = &$arr[$bit];
10900 }
10901 $arr[$last] = $val;
10902 } else {
10903 $config[$key] = $val;
10904 }
10905 });
10906 }
10907
10908
10909
10910
10911 public function removeProperty($name)
10912 {
10913 $authConfig = $this->authConfig;
10914 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
10915 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10916 $bits = explode('.', $key);
10917 $last = array_pop($bits);
10918 $arr = &$config[reset($bits)];
10919 foreach ($bits as $bit) {
10920 if (!isset($arr[$bit])) {
10921 return;
10922 }
10923 $arr = &$arr[$bit];
10924 }
10925 unset($arr[$last]);
10926 } else {
10927 unset($config[$key]);
10928 }
10929 });
10930 }
10931
10932
10933
10934
10935 public function addLink($type, $name, $value)
10936 {
10937 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
10938 $config[$type][$name] = $value;
10939 });
10940 }
10941
10942
10943
10944
10945 public function removeLink($type, $name)
10946 {
10947 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
10948 unset($config[$type][$name]);
10949
10950 if (0 === count($config[$type])) {
10951 unset($config[$type]);
10952 }
10953 });
10954 }
10955
10956 protected function manipulateJson($method, $args, $fallback)
10957 {
10958 $args = func_get_args();
10959
10960 array_shift($args);
10961 $fallback = array_pop($args);
10962
10963 if ($this->file->exists()) {
10964 if (!is_writable($this->file->getPath())) {
10965 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
10966 }
10967
10968 if (!is_readable($this->file->getPath())) {
10969 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
10970 }
10971
10972 $contents = file_get_contents($this->file->getPath());
10973 } elseif ($this->authConfig) {
10974 $contents = "{\n}\n";
10975 } else {
10976 $contents = "{\n    \"config\": {\n    }\n}\n";
10977 }
10978
10979 $manipulator = new JsonManipulator($contents);
10980
10981 $newFile = !$this->file->exists();
10982
10983
10984 if ($this->authConfig && $method === 'addConfigSetting') {
10985 $method = 'addSubNode';
10986 list($mainNode, $name) = explode('.', $args[0], 2);
10987 $args = array($mainNode, $name, $args[1]);
10988 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
10989 $method = 'removeSubNode';
10990 list($mainNode, $name) = explode('.', $args[0], 2);
10991 $args = array($mainNode, $name);
10992 }
10993
10994
10995 if (call_user_func_array(array($manipulator, $method), $args)) {
10996 file_put_contents($this->file->getPath(), $manipulator->getContents());
10997 } else {
10998
10999 $config = $this->file->read();
11000 $this->arrayUnshiftRef($args, $config);
11001 call_user_func_array($fallback, $args);
11002
11003 foreach (array('require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev') as $linkType) {
11004 if (isset($config[$linkType]) && $config[$linkType] === array()) {
11005 $config[$linkType] = new \stdClass;
11006 }
11007 }
11008 $this->file->write($config);
11009 }
11010
11011 if ($newFile) {
11012 Silencer::call('chmod', $this->file->getPath(), 0600);
11013 }
11014 }
11015
11016
11017
11018
11019
11020
11021
11022
11023 private function arrayUnshiftRef(&$array, &$value)
11024 {
11025 $return = array_unshift($array, '');
11026 $array[0] = &$value;
11027
11028 return $return;
11029 }
11030 }
11031 <?php
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043 namespace Composer\Console;
11044
11045 use Composer\IO\NullIO;
11046 use Composer\Util\Platform;
11047 use Composer\Util\Silencer;
11048 use Symfony\Component\Console\Application as BaseApplication;
11049 use Symfony\Component\Console\Exception\CommandNotFoundException;
11050 use Symfony\Component\Console\Helper\HelperSet;
11051 use Symfony\Component\Console\Helper\QuestionHelper;
11052 use Symfony\Component\Console\Input\InputInterface;
11053 use Symfony\Component\Console\Input\InputOption;
11054 use Symfony\Component\Console\Output\OutputInterface;
11055 use Composer\Command;
11056 use Composer\Composer;
11057 use Composer\Factory;
11058 use Composer\IO\IOInterface;
11059 use Composer\IO\ConsoleIO;
11060 use Composer\Json\JsonValidationException;
11061 use Composer\Util\ErrorHandler;
11062 use Composer\EventDispatcher\ScriptExecutionException;
11063 use Composer\Exception\NoSslException;
11064
11065
11066
11067
11068
11069
11070
11071
11072 class Application extends BaseApplication
11073 {
11074
11075
11076
11077 protected $composer;
11078
11079
11080
11081
11082 protected $io;
11083
11084 private static $logo = '   ______
11085   / ____/___  ____ ___  ____  ____  ________  _____
11086  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
11087 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
11088 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
11089                     /_/
11090 ';
11091
11092 private $hasPluginCommands = false;
11093 private $disablePluginsByDefault = false;
11094
11095
11096
11097
11098 private $initialWorkingDirectory = '';
11099
11100 public function __construct()
11101 {
11102 static $shutdownRegistered = false;
11103
11104 if (function_exists('ini_set') && extension_loaded('xdebug')) {
11105 ini_set('xdebug.show_exception_trace', false);
11106 ini_set('xdebug.scream', false);
11107 }
11108
11109 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
11110 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
11111 }
11112
11113 if (!$shutdownRegistered) {
11114 $shutdownRegistered = true;
11115
11116 register_shutdown_function(function () {
11117 $lastError = error_get_last();
11118
11119 if ($lastError && $lastError['message'] &&
11120 (strpos($lastError['message'], 'Allowed memory') !== false  ||
11121 strpos($lastError['message'], 'exceeded memory') !== false )) {
11122 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
11123 }
11124 });
11125 }
11126
11127 $this->io = new NullIO();
11128
11129 $this->initialWorkingDirectory = getcwd();
11130
11131 parent::__construct('Composer', Composer::getVersion());
11132 }
11133
11134
11135
11136
11137 public function run(InputInterface $input = null, OutputInterface $output = null)
11138 {
11139 if (null === $output) {
11140 $output = Factory::createOutput();
11141 }
11142
11143 return parent::run($input, $output);
11144 }
11145
11146
11147
11148
11149 public function doRun(InputInterface $input, OutputInterface $output)
11150 {
11151 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
11152
11153 if (getenv('COMPOSER_NO_INTERACTION')) {
11154 $input->setInteractive(false);
11155 }
11156
11157 $io = $this->io = new ConsoleIO($input, $output, new HelperSet(array(
11158 new QuestionHelper(),
11159 )));
11160
11161
11162 ErrorHandler::register($io);
11163
11164 if ($input->hasParameterOption('--no-cache')) {
11165 $io->writeError('Disabling cache usage', true, IOInterface::DEBUG);
11166 $_SERVER['COMPOSER_CACHE_DIR'] = Platform::isWindows() ? 'nul' : '/dev/null';
11167 putenv('COMPOSER_CACHE_DIR='.$_SERVER['COMPOSER_CACHE_DIR']);
11168 }
11169
11170
11171 if ($newWorkDir = $this->getNewWorkingDir($input)) {
11172 $oldWorkingDir = getcwd();
11173 chdir($newWorkDir);
11174 $this->initialWorkingDirectory = $newWorkDir;
11175 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
11176 }
11177
11178
11179 $commandName = '';
11180 if ($name = $this->getCommandName($input)) {
11181 try {
11182 $commandName = $this->find($name)->getName();
11183 } catch (CommandNotFoundException $e) {
11184
11185 $commandName = false;
11186 } catch (\InvalidArgumentException $e) {
11187 }
11188 }
11189
11190
11191 if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project', 'outdated'), true) && !file_exists(Factory::getComposerFile())) {
11192 $dir = dirname(getcwd());
11193 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
11194
11195
11196 while (dirname($dir) !== $dir && $dir !== $home) {
11197 if (file_exists($dir.'/'.Factory::getComposerFile())) {
11198 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)) {
11199 $oldWorkingDir = getcwd();
11200 chdir($dir);
11201 }
11202 break;
11203 }
11204 $dir = dirname($dir);
11205 }
11206 }
11207
11208 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
11209 try {
11210 foreach ($this->getPluginCommands() as $command) {
11211 if ($this->has($command->getName())) {
11212 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
11213 } else {
11214 $this->add($command);
11215 }
11216 }
11217 } catch (NoSslException $e) {
11218
11219 }
11220
11221 $this->hasPluginCommands = true;
11222 }
11223
11224
11225 $isProxyCommand = false;
11226 if ($name = $this->getCommandName($input)) {
11227 try {
11228 $command = $this->find($name);
11229 $commandName = $command->getName();
11230 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
11231 } catch (\InvalidArgumentException $e) {
11232 }
11233 }
11234
11235 if (!$isProxyCommand) {
11236 $io->writeError(sprintf(
11237 'Running %s (%s) with %s on %s',
11238 Composer::getVersion(),
11239 Composer::RELEASE_DATE,
11240 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
11241 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
11242 ), true, IOInterface::DEBUG);
11243
11244 if (PHP_VERSION_ID < 50302) {
11245 $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>');
11246 }
11247
11248 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
11249 $io->writeError('<warning>You are running composer with Xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
11250 }
11251
11252 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
11253 $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']));
11254 }
11255
11256 if (
11257 !Platform::isWindows()
11258 && function_exists('exec')
11259 && !getenv('COMPOSER_ALLOW_SUPERUSER')
11260 && (ini_get('open_basedir') || !file_exists('/.dockerenv'))
11261 ) {
11262 if (function_exists('posix_getuid') && posix_getuid() === 0) {
11263 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
11264 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
11265 }
11266 if ($uid = (int) getenv('SUDO_UID')) {
11267
11268
11269 Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
11270 }
11271 }
11272
11273 Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
11274 }
11275
11276
11277 Silencer::call(function () use ($io) {
11278 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
11279 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
11280 $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()));
11281 }
11282 });
11283
11284
11285 $file = Factory::getComposerFile();
11286 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
11287 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
11288 foreach ($composer['scripts'] as $script => $dummy) {
11289 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
11290 if ($this->has($script)) {
11291 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
11292 } else {
11293 $description = null;
11294
11295 if (isset($composer['scripts-descriptions'][$script])) {
11296 $description = $composer['scripts-descriptions'][$script];
11297 }
11298
11299 $this->add(new Command\ScriptAliasCommand($script, $description));
11300 }
11301 }
11302 }
11303 }
11304 }
11305 }
11306
11307 try {
11308 if ($input->hasParameterOption('--profile')) {
11309 $startTime = microtime(true);
11310 $this->io->enableDebugging($startTime);
11311 }
11312
11313 $result = parent::doRun($input, $output);
11314
11315 if (isset($oldWorkingDir)) {
11316 chdir($oldWorkingDir);
11317 }
11318
11319 if (isset($startTime)) {
11320 $io->writeError('<info>Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MiB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MiB), time: '.round(microtime(true) - $startTime, 2).'s');
11321 }
11322
11323 restore_error_handler();
11324
11325 return $result;
11326 } catch (ScriptExecutionException $e) {
11327 return $e->getCode();
11328 } catch (\Exception $e) {
11329 $this->hintCommonErrors($e);
11330 restore_error_handler();
11331 throw $e;
11332 }
11333 }
11334
11335
11336
11337
11338
11339
11340 private function getNewWorkingDir(InputInterface $input)
11341 {
11342 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
11343 if (false !== $workingDir && !is_dir($workingDir)) {
11344 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
11345 }
11346
11347 return $workingDir;
11348 }
11349
11350
11351
11352
11353 private function hintCommonErrors($exception)
11354 {
11355 $io = $this->getIO();
11356
11357 Silencer::suppress();
11358 try {
11359 $composer = $this->getComposer(false, true);
11360 if ($composer) {
11361 $config = $composer->getConfig();
11362
11363 $minSpaceFree = 1024 * 1024;
11364 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
11365 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
11366 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
11367 ) {
11368 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
11369 }
11370 }
11371 } catch (\Exception $e) {
11372 }
11373 Silencer::restore();
11374
11375 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
11376 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
11377 $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);
11378 }
11379
11380 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
11381 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
11382 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
11383 }
11384 }
11385
11386
11387
11388
11389
11390
11391
11392 public function getComposer($required = true, $disablePlugins = null)
11393 {
11394 if (null === $disablePlugins) {
11395 $disablePlugins = $this->disablePluginsByDefault;
11396 }
11397
11398 if (null === $this->composer) {
11399 try {
11400 $this->composer = Factory::create($this->io, null, $disablePlugins);
11401 } catch (\InvalidArgumentException $e) {
11402 if ($required) {
11403 $this->io->writeError($e->getMessage());
11404 exit(1);
11405 }
11406 } catch (JsonValidationException $e) {
11407 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
11408 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
11409 throw new JsonValidationException($message);
11410 }
11411 }
11412
11413 return $this->composer;
11414 }
11415
11416
11417
11418
11419 public function resetComposer()
11420 {
11421 $this->composer = null;
11422 if ($this->getIO() && method_exists($this->getIO(), 'resetAuthentications')) {
11423 $this->getIO()->resetAuthentications();
11424 }
11425 }
11426
11427
11428
11429
11430 public function getIO()
11431 {
11432 return $this->io;
11433 }
11434
11435 public function getHelp()
11436 {
11437 return self::$logo . parent::getHelp();
11438 }
11439
11440
11441
11442
11443 protected function getDefaultCommands()
11444 {
11445 $commands = array_merge(parent::getDefaultCommands(), array(
11446 new Command\AboutCommand(),
11447 new Command\ConfigCommand(),
11448 new Command\DependsCommand(),
11449 new Command\ProhibitsCommand(),
11450 new Command\InitCommand(),
11451 new Command\InstallCommand(),
11452 new Command\CreateProjectCommand(),
11453 new Command\UpdateCommand(),
11454 new Command\SearchCommand(),
11455 new Command\ValidateCommand(),
11456 new Command\ShowCommand(),
11457 new Command\SuggestsCommand(),
11458 new Command\RequireCommand(),
11459 new Command\DumpAutoloadCommand(),
11460 new Command\StatusCommand(),
11461 new Command\ArchiveCommand(),
11462 new Command\DiagnoseCommand(),
11463 new Command\RunScriptCommand(),
11464 new Command\LicensesCommand(),
11465 new Command\GlobalCommand(),
11466 new Command\ClearCacheCommand(),
11467 new Command\RemoveCommand(),
11468 new Command\HomeCommand(),
11469 new Command\ExecCommand(),
11470 new Command\OutdatedCommand(),
11471 new Command\CheckPlatformReqsCommand(),
11472 new Command\FundCommand(),
11473 ));
11474
11475 if ('phar:' === substr(__FILE__, 0, 5)) {
11476 $commands[] = new Command\SelfUpdateCommand();
11477 }
11478
11479 return $commands;
11480 }
11481
11482
11483
11484
11485 public function getLongVersion()
11486 {
11487 if (Composer::BRANCH_ALIAS_VERSION && Composer::BRANCH_ALIAS_VERSION !== '@package_branch_alias_version'.'@') {
11488 return sprintf(
11489 '<info>%s</info> version <comment>%s (%s)</comment> %s',
11490 $this->getName(),
11491 Composer::BRANCH_ALIAS_VERSION,
11492 $this->getVersion(),
11493 Composer::RELEASE_DATE
11494 );
11495 }
11496
11497 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
11498 }
11499
11500
11501
11502
11503 protected function getDefaultInputDefinition()
11504 {
11505 $definition = parent::getDefaultInputDefinition();
11506 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
11507 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
11508 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
11509 $definition->addOption(new InputOption('--no-cache', null, InputOption::VALUE_NONE, 'Prevent use of the cache'));
11510
11511 return $definition;
11512 }
11513
11514 private function getPluginCommands()
11515 {
11516 $commands = array();
11517
11518 $composer = $this->getComposer(false, false);
11519 if (null === $composer) {
11520 $composer = Factory::createGlobal($this->io, false);
11521 }
11522
11523 if (null !== $composer) {
11524 $pm = $composer->getPluginManager();
11525 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
11526 $newCommands = $capability->getCommands();
11527 if (!is_array($newCommands)) {
11528 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
11529 }
11530 foreach ($newCommands as $command) {
11531 if (!$command instanceof Command\BaseCommand) {
11532 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
11533 }
11534 }
11535 $commands = array_merge($commands, $newCommands);
11536 }
11537 }
11538
11539 return $commands;
11540 }
11541
11542
11543
11544
11545
11546
11547 public function getInitialWorkingDirectory()
11548 {
11549 return $this->initialWorkingDirectory;
11550 }
11551 }
11552 <?php
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564 namespace Composer\Console;
11565
11566 use Symfony\Component\Console\Formatter\OutputFormatter;
11567
11568
11569
11570
11571 class HtmlOutputFormatter extends OutputFormatter
11572 {
11573 private static $availableForegroundColors = array(
11574 30 => 'black',
11575 31 => 'red',
11576 32 => 'green',
11577 33 => 'yellow',
11578 34 => 'blue',
11579 35 => 'magenta',
11580 36 => 'cyan',
11581 37 => 'white',
11582 );
11583 private static $availableBackgroundColors = array(
11584 40 => 'black',
11585 41 => 'red',
11586 42 => 'green',
11587 43 => 'yellow',
11588 44 => 'blue',
11589 45 => 'magenta',
11590 46 => 'cyan',
11591 47 => 'white',
11592 );
11593 private static $availableOptions = array(
11594 1 => 'bold',
11595 4 => 'underscore',
11596
11597
11598
11599 );
11600
11601
11602
11603
11604 public function __construct(array $styles = array())
11605 {
11606 parent::__construct(true, $styles);
11607 }
11608
11609 public function format($message)
11610 {
11611 $formatted = parent::format($message);
11612
11613 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
11614
11615 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
11616 }
11617
11618 private function formatHtml($matches)
11619 {
11620 $out = '<span style="';
11621 foreach (explode(';', $matches[1]) as $code) {
11622 if (isset(self::$availableForegroundColors[$code])) {
11623 $out .= 'color:'.self::$availableForegroundColors[$code].';';
11624 } elseif (isset(self::$availableBackgroundColors[$code])) {
11625 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
11626 } elseif (isset(self::$availableOptions[$code])) {
11627 switch (self::$availableOptions[$code]) {
11628 case 'bold':
11629 $out .= 'font-weight:bold;';
11630 break;
11631
11632 case 'underscore':
11633 $out .= 'text-decoration:underline;';
11634 break;
11635 }
11636 }
11637 }
11638
11639 return $out.'">'.$matches[2].'</span>';
11640 }
11641 }
11642 <?php
11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654 namespace Composer\DependencyResolver;
11655
11656
11657
11658
11659
11660
11661 class Decisions implements \Iterator, \Countable
11662 {
11663 const DECISION_LITERAL = 0;
11664 const DECISION_REASON = 1;
11665
11666 protected $pool;
11667 protected $decisionMap;
11668 protected $decisionQueue = array();
11669
11670 public function __construct($pool)
11671 {
11672 $this->pool = $pool;
11673 $this->decisionMap = array();
11674 }
11675
11676 public function decide($literal, $level, $why)
11677 {
11678 $this->addDecision($literal, $level);
11679 $this->decisionQueue[] = array(
11680 self::DECISION_LITERAL => $literal,
11681 self::DECISION_REASON => $why,
11682 );
11683 }
11684
11685 public function satisfy($literal)
11686 {
11687 $packageId = abs($literal);
11688
11689 return (
11690 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
11691 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
11692 );
11693 }
11694
11695 public function conflict($literal)
11696 {
11697 $packageId = abs($literal);
11698
11699 return (
11700 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
11701 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
11702 );
11703 }
11704
11705 public function decided($literalOrPackageId)
11706 {
11707 return !empty($this->decisionMap[abs($literalOrPackageId)]);
11708 }
11709
11710 public function undecided($literalOrPackageId)
11711 {
11712 return empty($this->decisionMap[abs($literalOrPackageId)]);
11713 }
11714
11715 public function decidedInstall($literalOrPackageId)
11716 {
11717 $packageId = abs($literalOrPackageId);
11718
11719 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
11720 }
11721
11722 public function decisionLevel($literalOrPackageId)
11723 {
11724 $packageId = abs($literalOrPackageId);
11725 if (isset($this->decisionMap[$packageId])) {
11726 return abs($this->decisionMap[$packageId]);
11727 }
11728
11729 return 0;
11730 }
11731
11732 public function decisionRule($literalOrPackageId)
11733 {
11734 $packageId = abs($literalOrPackageId);
11735
11736 foreach ($this->decisionQueue as $i => $decision) {
11737 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
11738 return $decision[self::DECISION_REASON];
11739 }
11740 }
11741
11742 return null;
11743 }
11744
11745 public function atOffset($queueOffset)
11746 {
11747 return $this->decisionQueue[$queueOffset];
11748 }
11749
11750 public function validOffset($queueOffset)
11751 {
11752 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
11753 }
11754
11755 public function lastReason()
11756 {
11757 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
11758 }
11759
11760 public function lastLiteral()
11761 {
11762 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
11763 }
11764
11765 public function reset()
11766 {
11767 while ($decision = array_pop($this->decisionQueue)) {
11768 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
11769 }
11770 }
11771
11772 public function resetToOffset($offset)
11773 {
11774 while (count($this->decisionQueue) > $offset + 1) {
11775 $decision = array_pop($this->decisionQueue);
11776 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
11777 }
11778 }
11779
11780 public function revertLast()
11781 {
11782 $this->decisionMap[abs($this->lastLiteral())] = 0;
11783 array_pop($this->decisionQueue);
11784 }
11785
11786 public function count()
11787 {
11788 return count($this->decisionQueue);
11789 }
11790
11791 public function rewind()
11792 {
11793 end($this->decisionQueue);
11794 }
11795
11796 public function current()
11797 {
11798 return current($this->decisionQueue);
11799 }
11800
11801 public function key()
11802 {
11803 return key($this->decisionQueue);
11804 }
11805
11806 public function next()
11807 {
11808 return prev($this->decisionQueue);
11809 }
11810
11811 public function valid()
11812 {
11813 return false !== current($this->decisionQueue);
11814 }
11815
11816 public function isEmpty()
11817 {
11818 return count($this->decisionQueue) === 0;
11819 }
11820
11821 protected function addDecision($literal, $level)
11822 {
11823 $packageId = abs($literal);
11824
11825 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
11826 if ($previousDecision != 0) {
11827 $literalString = $this->pool->literalToPrettyString($literal, array());
11828 $package = $this->pool->literalToPackage($literal);
11829 throw new SolverBugException(
11830 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
11831 );
11832 }
11833
11834 if ($literal > 0) {
11835 $this->decisionMap[$packageId] = $level;
11836 } else {
11837 $this->decisionMap[$packageId] = -$level;
11838 }
11839 }
11840
11841 public function __toString()
11842 {
11843 $decisionMap = $this->decisionMap;
11844 ksort($decisionMap);
11845 $str = '[';
11846 foreach ($decisionMap as $packageId => $level) {
11847 $str .= $packageId.':'.$level.',';
11848 }
11849 $str .= ']';
11850 return $str;
11851 }
11852 }
11853 <?php
11854
11855
11856
11857
11858
11859
11860
11861
11862
11863
11864
11865 namespace Composer\DependencyResolver;
11866
11867 use Composer\Package\PackageInterface;
11868 use Composer\Package\AliasPackage;
11869 use Composer\Package\BasePackage;
11870 use Composer\Semver\Constraint\Constraint;
11871
11872
11873
11874
11875
11876 class DefaultPolicy implements PolicyInterface
11877 {
11878 private $preferStable;
11879 private $preferLowest;
11880
11881 public function __construct($preferStable = false, $preferLowest = false)
11882 {
11883 $this->preferStable = $preferStable;
11884 $this->preferLowest = $preferLowest;
11885 }
11886
11887 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
11888 {
11889 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
11890 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
11891 }
11892
11893 $constraint = new Constraint($operator, $b->getVersion());
11894 $version = new Constraint('==', $a->getVersion());
11895
11896 return $constraint->matchSpecific($version, true);
11897 }
11898
11899 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
11900 {
11901 $packages = array();
11902
11903 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
11904 if ($candidate !== $package) {
11905 $packages[] = $candidate;
11906 }
11907 }
11908
11909 return $packages;
11910 }
11911
11912 public function getPriority(Pool $pool, PackageInterface $package)
11913 {
11914 return $pool->getPriority($package->getRepository());
11915 }
11916
11917 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
11918 {
11919 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
11920
11921 foreach ($packages as &$literals) {
11922 $policy = $this;
11923 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11924 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
11925 });
11926 }
11927
11928 foreach ($packages as &$literals) {
11929 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
11930
11931 $literals = $this->pruneToBestVersion($pool, $literals);
11932
11933 $literals = $this->pruneRemoteAliases($pool, $literals);
11934 }
11935
11936 $selected = call_user_func_array('array_merge', array_values($packages));
11937
11938
11939 usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11940 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
11941 });
11942
11943 return $selected;
11944 }
11945
11946 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
11947 {
11948 $packages = array();
11949 foreach ($literals as $literal) {
11950 $packageName = $pool->literalToPackage($literal)->getName();
11951
11952 if (!isset($packages[$packageName])) {
11953 $packages[$packageName] = array();
11954 }
11955
11956 if (isset($installedMap[abs($literal)])) {
11957 array_unshift($packages[$packageName], $literal);
11958 } else {
11959 $packages[$packageName][] = $literal;
11960 }
11961 }
11962
11963 return $packages;
11964 }
11965
11966
11967
11968
11969 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
11970 {
11971 if ($a->getRepository() === $b->getRepository()) {
11972
11973 if ($a->getName() === $b->getName()) {
11974 $aAliased = $a instanceof AliasPackage;
11975 $bAliased = $b instanceof AliasPackage;
11976 if ($aAliased && !$bAliased) {
11977 return -1; 
11978 }
11979 if (!$aAliased && $bAliased) {
11980 return 1; 
11981 }
11982 }
11983
11984 if (!$ignoreReplace) {
11985
11986 if ($this->replaces($a, $b)) {
11987 return 1; 
11988 }
11989 if ($this->replaces($b, $a)) {
11990 return -1; 
11991 }
11992
11993
11994
11995 if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
11996 $requiredVendor = substr($requiredPackage, 0, $pos);
11997
11998 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
11999 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
12000
12001 if ($bIsSameVendor !== $aIsSameVendor) {
12002 return $aIsSameVendor ? -1 : 1;
12003 }
12004 }
12005 }
12006
12007
12008 if ($a->id === $b->id) {
12009 return 0;
12010 }
12011
12012 return ($a->id < $b->id) ? -1 : 1;
12013 }
12014
12015 if (isset($installedMap[$a->id])) {
12016 return -1;
12017 }
12018
12019 if (isset($installedMap[$b->id])) {
12020 return 1;
12021 }
12022
12023 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
12024 }
12025
12026
12027
12028
12029
12030
12031
12032
12033
12034
12035
12036 protected function replaces(PackageInterface $source, PackageInterface $target)
12037 {
12038 foreach ($source->getReplaces() as $link) {
12039 if ($link->getTarget() === $target->getName()
12040
12041
12042 ) {
12043 return true;
12044 }
12045 }
12046
12047 return false;
12048 }
12049
12050 protected function pruneToBestVersion(Pool $pool, $literals)
12051 {
12052 $operator = $this->preferLowest ? '<' : '>';
12053 $bestLiterals = array($literals[0]);
12054 $bestPackage = $pool->literalToPackage($literals[0]);
12055 foreach ($literals as $i => $literal) {
12056 if (0 === $i) {
12057 continue;
12058 }
12059
12060 $package = $pool->literalToPackage($literal);
12061
12062 if ($this->versionCompare($package, $bestPackage, $operator)) {
12063 $bestPackage = $package;
12064 $bestLiterals = array($literal);
12065 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
12066 $bestLiterals[] = $literal;
12067 }
12068 }
12069
12070 return $bestLiterals;
12071 }
12072
12073
12074
12075
12076 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
12077 {
12078 $selected = array();
12079
12080 $priority = null;
12081
12082 foreach ($literals as $literal) {
12083 $package = $pool->literalToPackage($literal);
12084
12085 if (isset($installedMap[$package->id])) {
12086 $selected[] = $literal;
12087 continue;
12088 }
12089
12090 if (null === $priority) {
12091 $priority = $this->getPriority($pool, $package);
12092 }
12093
12094 if ($this->getPriority($pool, $package) != $priority) {
12095 break;
12096 }
12097
12098 $selected[] = $literal;
12099 }
12100
12101 return $selected;
12102 }
12103
12104
12105
12106
12107
12108
12109 protected function pruneRemoteAliases(Pool $pool, array $literals)
12110 {
12111 $hasLocalAlias = false;
12112
12113 foreach ($literals as $literal) {
12114 $package = $pool->literalToPackage($literal);
12115
12116 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
12117 $hasLocalAlias = true;
12118 break;
12119 }
12120 }
12121
12122 if (!$hasLocalAlias) {
12123 return $literals;
12124 }
12125
12126 $selected = array();
12127 foreach ($literals as $literal) {
12128 $package = $pool->literalToPackage($literal);
12129
12130 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
12131 $selected[] = $literal;
12132 }
12133 }
12134
12135 return $selected;
12136 }
12137 }
12138 <?php
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150 namespace Composer\DependencyResolver;
12151
12152 use Composer\Package\PackageInterface;
12153 use Composer\Package\Link;
12154
12155
12156
12157
12158 class GenericRule extends Rule
12159 {
12160 protected $literals;
12161
12162
12163
12164
12165
12166
12167
12168 public function __construct(array $literals, $reason, $reasonData, $job = null)
12169 {
12170 parent::__construct($reason, $reasonData, $job);
12171
12172
12173 sort($literals);
12174
12175 $this->literals = $literals;
12176 }
12177
12178 public function getLiterals()
12179 {
12180 return $this->literals;
12181 }
12182
12183 public function getHash()
12184 {
12185 $data = unpack('ihash', md5(implode(',', $this->literals), true));
12186
12187 return $data['hash'];
12188 }
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198 public function equals(Rule $rule)
12199 {
12200 return $this->literals === $rule->getLiterals();
12201 }
12202
12203 public function isAssertion()
12204 {
12205 return 1 === count($this->literals);
12206 }
12207
12208
12209
12210
12211
12212
12213 public function __toString()
12214 {
12215 $result = $this->isDisabled() ? 'disabled(' : '(';
12216
12217 foreach ($this->literals as $i => $literal) {
12218 if ($i != 0) {
12219 $result .= '|';
12220 }
12221 $result .= $literal;
12222 }
12223
12224 $result .= ')';
12225
12226 return $result;
12227 }
12228 }
12229 <?php
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241 namespace Composer\DependencyResolver\Operation;
12242
12243 use Composer\Package\PackageInterface;
12244
12245
12246
12247
12248
12249
12250 class InstallOperation extends SolverOperation
12251 {
12252 protected $package;
12253
12254
12255
12256
12257
12258
12259
12260 public function __construct(PackageInterface $package, $reason = null)
12261 {
12262 parent::__construct($reason);
12263
12264 $this->package = $package;
12265 }
12266
12267
12268
12269
12270
12271
12272 public function getPackage()
12273 {
12274 return $this->package;
12275 }
12276
12277
12278
12279
12280
12281
12282 public function getJobType()
12283 {
12284 return 'install';
12285 }
12286
12287
12288
12289
12290 public function __toString()
12291 {
12292 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
12293 }
12294 }
12295 <?php
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307 namespace Composer\DependencyResolver\Operation;
12308
12309 use Composer\Package\AliasPackage;
12310 use Composer\Package\PackageInterface;
12311
12312
12313
12314
12315
12316
12317 class MarkAliasInstalledOperation extends SolverOperation
12318 {
12319 protected $package;
12320
12321
12322
12323
12324
12325
12326
12327 public function __construct(AliasPackage $package, $reason = null)
12328 {
12329 parent::__construct($reason);
12330
12331 $this->package = $package;
12332 }
12333
12334
12335
12336
12337
12338
12339 public function getPackage()
12340 {
12341 return $this->package;
12342 }
12343
12344
12345
12346
12347
12348
12349 public function getJobType()
12350 {
12351 return 'markAliasInstalled';
12352 }
12353
12354
12355
12356
12357 public function __toString()
12358 {
12359 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
12360 }
12361 }
12362 <?php
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374 namespace Composer\DependencyResolver\Operation;
12375
12376 use Composer\Package\AliasPackage;
12377 use Composer\Package\PackageInterface;
12378
12379
12380
12381
12382
12383
12384 class MarkAliasUninstalledOperation extends SolverOperation
12385 {
12386 protected $package;
12387
12388
12389
12390
12391
12392
12393
12394 public function __construct(AliasPackage $package, $reason = null)
12395 {
12396 parent::__construct($reason);
12397
12398 $this->package = $package;
12399 }
12400
12401
12402
12403
12404
12405
12406 public function getPackage()
12407 {
12408 return $this->package;
12409 }
12410
12411
12412
12413
12414
12415
12416 public function getJobType()
12417 {
12418 return 'markAliasUninstalled';
12419 }
12420
12421
12422
12423
12424 public function __toString()
12425 {
12426 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
12427 }
12428 }
12429 <?php
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441 namespace Composer\DependencyResolver\Operation;
12442
12443
12444
12445
12446
12447
12448 interface OperationInterface
12449 {
12450
12451
12452
12453
12454
12455 public function getJobType();
12456
12457
12458
12459
12460
12461
12462 public function getReason();
12463
12464
12465
12466
12467
12468
12469 public function __toString();
12470 }
12471 <?php
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483 namespace Composer\DependencyResolver\Operation;
12484
12485 use Composer\Package\PackageInterface;
12486
12487
12488
12489
12490
12491
12492 abstract class SolverOperation implements OperationInterface
12493 {
12494 protected $reason;
12495
12496
12497
12498
12499
12500
12501 public function __construct($reason = null)
12502 {
12503 $this->reason = $reason;
12504 }
12505
12506
12507
12508
12509
12510
12511 public function getReason()
12512 {
12513 return $this->reason;
12514 }
12515
12516 protected function formatVersion(PackageInterface $package)
12517 {
12518 return $package->getFullPrettyVersion();
12519 }
12520 }
12521 <?php
12522
12523
12524
12525
12526
12527
12528
12529
12530
12531
12532
12533 namespace Composer\DependencyResolver\Operation;
12534
12535 use Composer\Package\PackageInterface;
12536
12537
12538
12539
12540
12541
12542 class UninstallOperation extends SolverOperation
12543 {
12544 protected $package;
12545
12546
12547
12548
12549
12550
12551
12552 public function __construct(PackageInterface $package, $reason = null)
12553 {
12554 parent::__construct($reason);
12555
12556 $this->package = $package;
12557 }
12558
12559
12560
12561
12562
12563
12564 public function getPackage()
12565 {
12566 return $this->package;
12567 }
12568
12569
12570
12571
12572
12573
12574 public function getJobType()
12575 {
12576 return 'uninstall';
12577 }
12578
12579
12580
12581
12582 public function __toString()
12583 {
12584 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
12585 }
12586 }
12587 <?php
12588
12589
12590
12591
12592
12593
12594
12595
12596
12597
12598
12599 namespace Composer\DependencyResolver\Operation;
12600
12601 use Composer\Package\PackageInterface;
12602 use Composer\Package\Version\VersionParser;
12603
12604
12605
12606
12607
12608
12609 class UpdateOperation extends SolverOperation
12610 {
12611 protected $initialPackage;
12612 protected $targetPackage;
12613
12614
12615
12616
12617
12618
12619
12620
12621 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
12622 {
12623 parent::__construct($reason);
12624
12625 $this->initialPackage = $initial;
12626 $this->targetPackage = $target;
12627 }
12628
12629
12630
12631
12632
12633
12634 public function getInitialPackage()
12635 {
12636 return $this->initialPackage;
12637 }
12638
12639
12640
12641
12642
12643
12644 public function getTargetPackage()
12645 {
12646 return $this->targetPackage;
12647 }
12648
12649
12650
12651
12652
12653
12654 public function getJobType()
12655 {
12656 return 'update';
12657 }
12658
12659
12660
12661
12662 public function __toString()
12663 {
12664 $actionName = VersionParser::isUpgrade($this->initialPackage->getVersion(), $this->targetPackage->getVersion()) ? 'Updating' : 'Downgrading';
12665
12666 return $actionName.' '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
12667 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
12668 }
12669 }
12670 <?php
12671
12672
12673
12674
12675
12676
12677
12678
12679
12680
12681
12682 namespace Composer\DependencyResolver;
12683
12684 use Composer\Package\PackageInterface;
12685
12686
12687
12688
12689 interface PolicyInterface
12690 {
12691 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
12692
12693 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
12694
12695 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
12696 }
12697 <?php
12698
12699
12700
12701
12702
12703
12704
12705
12706
12707
12708
12709 namespace Composer\DependencyResolver;
12710
12711 use Composer\Package\BasePackage;
12712 use Composer\Package\AliasPackage;
12713 use Composer\Package\Version\VersionParser;
12714 use Composer\Semver\Constraint\ConstraintInterface;
12715 use Composer\Semver\Constraint\Constraint;
12716 use Composer\Semver\Constraint\EmptyConstraint;
12717 use Composer\Repository\RepositoryInterface;
12718 use Composer\Repository\CompositeRepository;
12719 use Composer\Repository\ComposerRepository;
12720 use Composer\Repository\InstalledRepositoryInterface;
12721 use Composer\Repository\PlatformRepository;
12722 use Composer\Package\PackageInterface;
12723
12724
12725
12726
12727
12728
12729
12730 class Pool implements \Countable
12731 {
12732 const MATCH_NAME = -1;
12733 const MATCH_NONE = 0;
12734 const MATCH = 1;
12735 const MATCH_PROVIDE = 2;
12736 const MATCH_REPLACE = 3;
12737 const MATCH_FILTERED = 4;
12738
12739 protected $repositories = array();
12740 protected $providerRepos = array();
12741 protected $packages = array();
12742 protected $packageByName = array();
12743 protected $packageByExactName = array();
12744 protected $acceptableStabilities;
12745 protected $stabilityFlags;
12746 protected $versionParser;
12747 protected $providerCache = array();
12748 protected $filterRequires;
12749 protected $whitelist = null; 
12750 protected $id = 1;
12751
12752 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
12753 {
12754 $this->versionParser = new VersionParser;
12755 $this->acceptableStabilities = array();
12756 foreach (BasePackage::$stabilities as $stability => $value) {
12757 if ($value <= BasePackage::$stabilities[$minimumStability]) {
12758 $this->acceptableStabilities[$stability] = $value;
12759 }
12760 }
12761 $this->stabilityFlags = $stabilityFlags;
12762 $this->filterRequires = $filterRequires;
12763 foreach ($filterRequires as $name => $constraint) {
12764 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
12765 unset($this->filterRequires[$name]);
12766 }
12767 }
12768 }
12769
12770 public function setAllowList($allowList)
12771 {
12772
12773 $this->setWhitelist($allowList);
12774 }
12775
12776
12777
12778
12779 public function setWhitelist($whitelist)
12780 {
12781 $this->whitelist = $whitelist;
12782 $this->providerCache = array();
12783 }
12784
12785
12786
12787
12788
12789
12790
12791 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
12792 {
12793 if ($repo instanceof CompositeRepository) {
12794 $repos = $repo->getRepositories();
12795 } else {
12796 $repos = array($repo);
12797 }
12798
12799 foreach ($repos as $repo) {
12800 $this->repositories[] = $repo;
12801
12802 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
12803
12804 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
12805 $this->providerRepos[] = $repo;
12806 $repo->setRootAliases($rootAliases);
12807 $repo->resetPackageIds();
12808 } else {
12809 foreach ($repo->getPackages() as $package) {
12810 $names = $package->getNames();
12811 $stability = $package->getStability();
12812 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
12813 $package->setId($this->id++);
12814 $this->packages[] = $package;
12815 $this->packageByExactName[$package->getName()][$package->id] = $package;
12816
12817 foreach ($names as $provided) {
12818 $this->packageByName[$provided][] = $package;
12819 }
12820
12821
12822 $name = $package->getName();
12823 if (isset($rootAliases[$name][$package->getVersion()])) {
12824 $alias = $rootAliases[$name][$package->getVersion()];
12825 if ($package instanceof AliasPackage) {
12826 $package = $package->getAliasOf();
12827 }
12828 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
12829 $aliasPackage->setRootPackageAlias(true);
12830 $aliasPackage->setId($this->id++);
12831
12832 $package->getRepository()->addPackage($aliasPackage);
12833 $this->packages[] = $aliasPackage;
12834 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
12835
12836 foreach ($aliasPackage->getNames() as $name) {
12837 $this->packageByName[$name][] = $aliasPackage;
12838 }
12839 }
12840 }
12841 }
12842 }
12843 }
12844 }
12845
12846 public function getPriority(RepositoryInterface $repo)
12847 {
12848 $priority = array_search($repo, $this->repositories, true);
12849
12850 if (false === $priority) {
12851 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
12852 }
12853
12854 return -$priority;
12855 }
12856
12857
12858
12859
12860
12861
12862
12863 public function packageById($id)
12864 {
12865 return $this->packages[$id - 1];
12866 }
12867
12868
12869
12870
12871 public function count()
12872 {
12873 return count($this->packages);
12874 }
12875
12876
12877
12878
12879
12880
12881
12882
12883
12884
12885
12886
12887 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
12888 {
12889 if ($bypassFilters) {
12890 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
12891 }
12892
12893 $key = ((int) $mustMatchName).$constraint;
12894 if (isset($this->providerCache[$name][$key])) {
12895 return $this->providerCache[$name][$key];
12896 }
12897
12898 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
12899 }
12900
12901
12902
12903
12904 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
12905 {
12906 $candidates = array();
12907
12908 foreach ($this->providerRepos as $repo) {
12909 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
12910 $candidates[] = $candidate;
12911 if ($candidate->id < 1) {
12912 $candidate->setId($this->id++);
12913 $this->packages[$this->id - 2] = $candidate;
12914 }
12915 }
12916 }
12917
12918 if ($mustMatchName) {
12919 $candidates = array_filter($candidates, function ($candidate) use ($name) {
12920 return $candidate->getName() == $name;
12921 });
12922 if (isset($this->packageByExactName[$name])) {
12923 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
12924 }
12925 } elseif (isset($this->packageByName[$name])) {
12926 $candidates = array_merge($candidates, $this->packageByName[$name]);
12927 }
12928
12929 $matches = $provideMatches = array();
12930 $nameMatch = false;
12931
12932 foreach ($candidates as $candidate) {
12933 $aliasOfCandidate = null;
12934
12935
12936
12937 if ($candidate instanceof AliasPackage) {
12938 $aliasOfCandidate = $candidate->getAliasOf();
12939 }
12940
12941 if ($this->whitelist !== null && !$bypassFilters && (
12942 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
12943 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
12944 )) {
12945 continue;
12946 }
12947 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
12948 case self::MATCH_NONE:
12949 break;
12950
12951 case self::MATCH_NAME:
12952 $nameMatch = true;
12953 break;
12954
12955 case self::MATCH:
12956 $nameMatch = true;
12957 $matches[] = $candidate;
12958 break;
12959
12960 case self::MATCH_PROVIDE:
12961 $provideMatches[] = $candidate;
12962 break;
12963
12964 case self::MATCH_REPLACE:
12965 $matches[] = $candidate;
12966 break;
12967
12968 case self::MATCH_FILTERED:
12969 break;
12970
12971 default:
12972 throw new \UnexpectedValueException('Unexpected match type');
12973 }
12974 }
12975
12976
12977 if ($nameMatch) {
12978 return $matches;
12979 }
12980
12981 return array_merge($matches, $provideMatches);
12982 }
12983
12984 public function literalToPackage($literal)
12985 {
12986 $packageId = abs($literal);
12987
12988 return $this->packageById($packageId);
12989 }
12990
12991 public function literalToPrettyString($literal, $installedMap)
12992 {
12993 $package = $this->literalToPackage($literal);
12994
12995 if (isset($installedMap[$package->id])) {
12996 $prefix = ($literal > 0 ? 'keep' : 'remove');
12997 } else {
12998 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
12999 }
13000
13001 return $prefix.' '.$package->getPrettyString();
13002 }
13003
13004 public function isPackageAcceptable($name, $stability)
13005 {
13006 foreach ((array) $name as $n) {
13007
13008 if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
13009 return true;
13010 }
13011
13012
13013 if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
13014 return true;
13015 }
13016 }
13017
13018 return false;
13019 }
13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030 public function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
13031 {
13032 $candidateName = $candidate->getName();
13033 $candidateVersion = $candidate->getVersion();
13034 $isDev = $candidate->getStability() === 'dev';
13035 $isAlias = $candidate instanceof AliasPackage;
13036
13037 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
13038 $requireFilter = $this->filterRequires[$name];
13039 } else {
13040 $requireFilter = new EmptyConstraint;
13041 }
13042
13043 if ($candidateName === $name) {
13044 $pkgConstraint = new Constraint('==', $candidateVersion);
13045
13046 if ($constraint === null || $constraint->matches($pkgConstraint)) {
13047 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
13048 }
13049
13050 return self::MATCH_NAME;
13051 }
13052
13053 $provides = $candidate->getProvides();
13054 $replaces = $candidate->getReplaces();
13055
13056
13057 if (isset($replaces[0]) || isset($provides[0])) {
13058 foreach ($provides as $link) {
13059 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
13060 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
13061 }
13062 }
13063
13064 foreach ($replaces as $link) {
13065 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
13066 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
13067 }
13068 }
13069
13070 return self::MATCH_NONE;
13071 }
13072
13073 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
13074 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
13075 }
13076
13077 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
13078 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
13079 }
13080
13081 return self::MATCH_NONE;
13082 }
13083 }
13084 <?php
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096 namespace Composer\DependencyResolver;
13097
13098 use Composer\Package\CompletePackageInterface;
13099
13100
13101
13102
13103
13104
13105 class Problem
13106 {
13107
13108
13109
13110
13111 protected $reasonSeen;
13112
13113
13114
13115
13116
13117 protected $reasons = array();
13118
13119 protected $section = 0;
13120
13121 protected $pool;
13122
13123 public function __construct(Pool $pool)
13124 {
13125 $this->pool = $pool;
13126 }
13127
13128
13129
13130
13131
13132
13133 public function addRule(Rule $rule)
13134 {
13135 $this->addReason(spl_object_hash($rule), array(
13136 'rule' => $rule,
13137 'job' => $rule->getJob(),
13138 ));
13139 }
13140
13141
13142
13143
13144
13145
13146 public function getReasons()
13147 {
13148 return $this->reasons;
13149 }
13150
13151
13152
13153
13154
13155
13156
13157 public function getPrettyString(array $installedMap = array())
13158 {
13159 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
13160
13161 if (count($reasons) === 1) {
13162 reset($reasons);
13163 $reason = current($reasons);
13164
13165 $job = $reason['job'];
13166
13167 $packageName = $job['packageName'];
13168 $constraint = $job['constraint'];
13169
13170 if (isset($constraint)) {
13171 $packages = $this->pool->whatProvides($packageName, $constraint);
13172 } else {
13173 $packages = array();
13174 }
13175
13176 if ($job && $job['cmd'] === 'install' && empty($packages)) {
13177
13178
13179 if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
13180 $version = phpversion();
13181 $available = $this->pool->whatProvides($packageName);
13182
13183 if (count($available)) {
13184 $firstAvailable = reset($available);
13185 $version = $firstAvailable->getPrettyVersion();
13186 $extra = $firstAvailable->getExtra();
13187 if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
13188 $version .= '; ' . $firstAvailable->getDescription();
13189 }
13190 }
13191
13192 $msg = "\n    - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
13193
13194 if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
13195 return $msg . 'your HHVM version does not satisfy that requirement.';
13196 }
13197
13198 if ($packageName === 'hhvm') {
13199 return $msg . 'you are running this with PHP and not HHVM.';
13200 }
13201
13202 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
13203 }
13204
13205
13206 if (0 === stripos($packageName, 'ext-')) {
13207 if (false !== strpos($packageName, ' ')) {
13208 return "\n    - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
13209 }
13210
13211 $ext = substr($packageName, 4);
13212 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
13213
13214 return "\n    - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
13215 }
13216
13217
13218 if (0 === stripos($packageName, 'lib-')) {
13219 if (strtolower($packageName) === 'lib-icu') {
13220 $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.';
13221
13222 return "\n    - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
13223 }
13224
13225 return "\n    - The requested linked library ".$packageName.$this->constraintToText($constraint).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
13226 }
13227
13228 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
13229 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
13230
13231 return "\n    - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
13232 }
13233
13234 if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
13235 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
13236 }
13237
13238 if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
13239 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
13240 }
13241
13242 return "\n    - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
13243 }
13244 }
13245
13246 $messages = array();
13247
13248 foreach ($reasons as $reason) {
13249 $rule = $reason['rule'];
13250 $job = $reason['job'];
13251
13252 if ($job) {
13253 $messages[] = $this->jobToText($job);
13254 } elseif ($rule) {
13255 if ($rule instanceof Rule) {
13256 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
13257 }
13258 }
13259 }
13260
13261 return "\n    - ".implode("\n    - ", $messages);
13262 }
13263
13264
13265
13266
13267
13268
13269
13270 protected function addReason($id, $reason)
13271 {
13272 if (!isset($this->reasonSeen[$id])) {
13273 $this->reasonSeen[$id] = true;
13274 $this->reasons[$this->section][] = $reason;
13275 }
13276 }
13277
13278 public function nextSection()
13279 {
13280 $this->section++;
13281 }
13282
13283
13284
13285
13286
13287
13288
13289 protected function jobToText($job)
13290 {
13291 $packageName = $job['packageName'];
13292 $constraint = $job['constraint'];
13293 switch ($job['cmd']) {
13294 case 'install':
13295 $packages = $this->pool->whatProvides($packageName, $constraint);
13296 if (!$packages) {
13297 return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
13298 }
13299
13300 return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
13301 case 'update':
13302 return 'Update request for '.$packageName.$this->constraintToText($constraint).'.';
13303 case 'remove':
13304 return 'Removal request for '.$packageName.$this->constraintToText($constraint).'';
13305 }
13306
13307 if (isset($constraint)) {
13308 $packages = $this->pool->whatProvides($packageName, $constraint);
13309 } else {
13310 $packages = array();
13311 }
13312
13313 return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
13314 }
13315
13316 protected function getPackageList($packages)
13317 {
13318 $prepared = array();
13319 foreach ($packages as $package) {
13320 $prepared[$package->getName()]['name'] = $package->getPrettyName();
13321 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
13322 }
13323 foreach ($prepared as $name => $package) {
13324 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
13325 }
13326
13327 return implode(', ', $prepared);
13328 }
13329
13330
13331
13332
13333
13334
13335
13336 protected function constraintToText($constraint)
13337 {
13338 return $constraint ? ' '.$constraint->getPrettyString() : '';
13339 }
13340 }
13341 <?php
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353 namespace Composer\DependencyResolver;
13354
13355 use Composer\Semver\Constraint\ConstraintInterface;
13356
13357
13358
13359
13360 class Request
13361 {
13362 protected $jobs;
13363
13364 public function __construct()
13365 {
13366 $this->jobs = array();
13367 }
13368
13369 public function install($packageName, ConstraintInterface $constraint = null)
13370 {
13371 $this->addJob($packageName, 'install', $constraint);
13372 }
13373
13374 public function update($packageName, ConstraintInterface $constraint = null)
13375 {
13376 $this->addJob($packageName, 'update', $constraint);
13377 }
13378
13379 public function remove($packageName, ConstraintInterface $constraint = null)
13380 {
13381 $this->addJob($packageName, 'remove', $constraint);
13382 }
13383
13384
13385
13386
13387
13388
13389
13390
13391
13392 public function fix($packageName, ConstraintInterface $constraint = null)
13393 {
13394 $this->addJob($packageName, 'install', $constraint, true);
13395 }
13396
13397 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
13398 {
13399 $packageName = strtolower($packageName);
13400
13401 $this->jobs[] = array(
13402 'cmd' => $cmd,
13403 'packageName' => $packageName,
13404 'constraint' => $constraint,
13405 'fixed' => $fixed,
13406 );
13407 }
13408
13409 public function updateAll()
13410 {
13411 $this->jobs[] = array('cmd' => 'update-all');
13412 }
13413
13414 public function getJobs()
13415 {
13416 return $this->jobs;
13417 }
13418 }
13419 <?php
13420
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431 namespace Composer\DependencyResolver;
13432
13433 use Composer\Package\CompletePackage;
13434 use Composer\Package\Link;
13435 use Composer\Package\PackageInterface;
13436
13437
13438
13439
13440
13441 abstract class Rule
13442 {
13443
13444 const RULE_INTERNAL_ALLOW_UPDATE = 1;
13445 const RULE_JOB_INSTALL = 2;
13446 const RULE_JOB_REMOVE = 3;
13447 const RULE_PACKAGE_CONFLICT = 6;
13448 const RULE_PACKAGE_REQUIRES = 7;
13449 const RULE_PACKAGE_OBSOLETES = 8;
13450 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
13451 const RULE_PACKAGE_SAME_NAME = 10;
13452 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
13453 const RULE_LEARNED = 12;
13454 const RULE_PACKAGE_ALIAS = 13;
13455
13456
13457 const BITFIELD_TYPE = 0;
13458 const BITFIELD_REASON = 8;
13459 const BITFIELD_DISABLED = 16;
13460
13461 protected $bitfield;
13462 protected $job;
13463 protected $reasonData;
13464
13465
13466
13467
13468
13469
13470 public function __construct($reason, $reasonData, $job = null)
13471 {
13472 $this->reasonData = $reasonData;
13473
13474 if ($job) {
13475 $this->job = $job;
13476 }
13477
13478 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
13479 ($reason << self::BITFIELD_REASON) |
13480 (255 << self::BITFIELD_TYPE);
13481 }
13482
13483 abstract public function getLiterals();
13484
13485 abstract public function getHash();
13486
13487 public function getJob()
13488 {
13489 return $this->job;
13490 }
13491
13492 abstract public function equals(Rule $rule);
13493
13494 public function getReason()
13495 {
13496 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
13497 }
13498
13499 public function getReasonData()
13500 {
13501 return $this->reasonData;
13502 }
13503
13504 public function getRequiredPackage()
13505 {
13506 if ($this->getReason() === self::RULE_JOB_INSTALL) {
13507 return $this->reasonData;
13508 }
13509
13510 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
13511 return $this->reasonData->getTarget();
13512 }
13513 }
13514
13515 public function setType($type)
13516 {
13517 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
13518 }
13519
13520 public function getType()
13521 {
13522 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
13523 }
13524
13525 public function disable()
13526 {
13527 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
13528 }
13529
13530 public function enable()
13531 {
13532 $this->bitfield &= ~(255 << self::BITFIELD_DISABLED);
13533 }
13534
13535 public function isDisabled()
13536 {
13537 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
13538 }
13539
13540 public function isEnabled()
13541 {
13542 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
13543 }
13544
13545 abstract public function isAssertion();
13546
13547 public function getPrettyString(Pool $pool, array $installedMap = array())
13548 {
13549 $literals = $this->getLiterals();
13550
13551 $ruleText = '';
13552 foreach ($literals as $i => $literal) {
13553 if ($i != 0) {
13554 $ruleText .= '|';
13555 }
13556 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
13557 }
13558
13559 switch ($this->getReason()) {
13560 case self::RULE_INTERNAL_ALLOW_UPDATE:
13561 return $ruleText;
13562
13563 case self::RULE_JOB_INSTALL:
13564 return "Install command rule ($ruleText)";
13565
13566 case self::RULE_JOB_REMOVE:
13567 return "Remove command rule ($ruleText)";
13568
13569 case self::RULE_PACKAGE_CONFLICT:
13570 $package1 = $pool->literalToPackage($literals[0]);
13571 $package2 = $pool->literalToPackage($literals[1]);
13572
13573 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
13574
13575 case self::RULE_PACKAGE_REQUIRES:
13576 $sourceLiteral = array_shift($literals);
13577 $sourcePackage = $pool->literalToPackage($sourceLiteral);
13578
13579 $requires = array();
13580 foreach ($literals as $literal) {
13581 $requires[] = $pool->literalToPackage($literal);
13582 }
13583
13584 $text = $this->reasonData->getPrettyString($sourcePackage);
13585 if ($requires) {
13586 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
13587 } else {
13588 $targetName = $this->reasonData->getTarget();
13589
13590 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
13591
13592 if (defined('HHVM_VERSION')) {
13593 return $text . ' -> your HHVM version does not satisfy that requirement.';
13594 }
13595
13596 $packages = $pool->whatProvides($targetName);
13597 $package = count($packages) ? current($packages) : phpversion();
13598
13599 if ($targetName === 'hhvm') {
13600 if ($package instanceof CompletePackage) {
13601 return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
13602 } else {
13603 return $text . ' -> you are running this with PHP and not HHVM.';
13604 }
13605 }
13606
13607
13608 if (!($package instanceof CompletePackage)) {
13609 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
13610 }
13611
13612 $extra = $package->getExtra();
13613
13614 if (!empty($extra['config.platform'])) {
13615 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
13616 } else {
13617 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
13618 }
13619
13620 return $text;
13621 }
13622
13623 if (0 === strpos($targetName, 'ext-')) {
13624
13625 $ext = substr($targetName, 4);
13626 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
13627
13628 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
13629 }
13630
13631 if (0 === strpos($targetName, 'lib-')) {
13632
13633 $lib = substr($targetName, 4);
13634
13635 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.';
13636 }
13637
13638 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
13639 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
13640 }
13641
13642 return $text . ' -> no matching package found.';
13643 }
13644
13645 return $text;
13646
13647 case self::RULE_PACKAGE_OBSOLETES:
13648 return $ruleText;
13649 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
13650 return $ruleText;
13651 case self::RULE_PACKAGE_SAME_NAME:
13652 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
13653 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
13654 return $ruleText;
13655 case self::RULE_LEARNED:
13656 return 'Conclusion: '.$ruleText;
13657 case self::RULE_PACKAGE_ALIAS:
13658 return $ruleText;
13659 default:
13660 return '('.$ruleText.')';
13661 }
13662 }
13663
13664
13665
13666
13667
13668
13669
13670 protected function formatPackagesUnique($pool, array $packages)
13671 {
13672 $prepared = array();
13673 foreach ($packages as $package) {
13674 if (!is_object($package)) {
13675 $package = $pool->literalToPackage($package);
13676 }
13677 $prepared[$package->getName()]['name'] = $package->getPrettyName();
13678 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
13679 }
13680 foreach ($prepared as $name => $package) {
13681 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
13682 }
13683
13684 return implode(', ', $prepared);
13685 }
13686 }
13687 <?php
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697
13698
13699 namespace Composer\DependencyResolver;
13700
13701 use Composer\Package\PackageInterface;
13702 use Composer\Package\Link;
13703
13704
13705
13706
13707 class Rule2Literals extends Rule
13708 {
13709 protected $literal1;
13710 protected $literal2;
13711
13712
13713
13714
13715
13716
13717
13718
13719 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
13720 {
13721 parent::__construct($reason, $reasonData, $job);
13722
13723 if ($literal1 < $literal2) {
13724 $this->literal1 = $literal1;
13725 $this->literal2 = $literal2;
13726 } else {
13727 $this->literal1 = $literal2;
13728 $this->literal2 = $literal1;
13729 }
13730 }
13731
13732 public function getLiterals()
13733 {
13734 return array($this->literal1, $this->literal2);
13735 }
13736
13737 public function getHash()
13738 {
13739 return $this->literal1.','.$this->literal2;
13740 }
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750 public function equals(Rule $rule)
13751 {
13752
13753 if ($rule instanceof self) {
13754 if ($this->literal1 !== $rule->literal1) {
13755 return false;
13756 }
13757
13758 if ($this->literal2 !== $rule->literal2) {
13759 return false;
13760 }
13761
13762 return true;
13763 }
13764
13765 $literals = $rule->getLiterals();
13766 if (2 != count($literals)) {
13767 return false;
13768 }
13769
13770 if ($this->literal1 !== $literals[0]) {
13771 return false;
13772 }
13773
13774 if ($this->literal2 !== $literals[1]) {
13775 return false;
13776 }
13777
13778 return true;
13779 }
13780
13781 public function isAssertion()
13782 {
13783 return false;
13784 }
13785
13786
13787
13788
13789
13790
13791 public function __toString()
13792 {
13793 $result = $this->isDisabled() ? 'disabled(' : '(';
13794
13795 $result .= $this->literal1 . '|' . $this->literal2 . ')';
13796
13797 return $result;
13798 }
13799 }
13800 <?php
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812 namespace Composer\DependencyResolver;
13813
13814
13815
13816
13817 class RuleSet implements \IteratorAggregate, \Countable
13818 {
13819
13820 const TYPE_PACKAGE = 0;
13821 const TYPE_JOB = 1;
13822 const TYPE_LEARNED = 4;
13823
13824
13825
13826
13827
13828
13829 public $ruleById;
13830
13831 protected static $types = array(
13832 255 => 'UNKNOWN',
13833 self::TYPE_PACKAGE => 'PACKAGE',
13834 self::TYPE_JOB => 'JOB',
13835 self::TYPE_LEARNED => 'LEARNED',
13836 );
13837
13838 protected $rules;
13839 protected $nextRuleId;
13840
13841 protected $rulesByHash;
13842
13843 public function __construct()
13844 {
13845 $this->nextRuleId = 0;
13846
13847 foreach ($this->getTypes() as $type) {
13848 $this->rules[$type] = array();
13849 }
13850
13851 $this->rulesByHash = array();
13852 }
13853
13854 public function add(Rule $rule, $type)
13855 {
13856 if (!isset(self::$types[$type])) {
13857 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
13858 }
13859
13860 $hash = $rule->getHash();
13861
13862
13863 if (isset($this->rulesByHash[$hash])) {
13864 $potentialDuplicates = $this->rulesByHash[$hash];
13865 if (is_array($potentialDuplicates)) {
13866 foreach ($potentialDuplicates as $potentialDuplicate) {
13867 if ($rule->equals($potentialDuplicate)) {
13868 return;
13869 }
13870 }
13871 } else {
13872 if ($rule->equals($potentialDuplicates)) {
13873 return;
13874 }
13875 }
13876 }
13877
13878 if (!isset($this->rules[$type])) {
13879 $this->rules[$type] = array();
13880 }
13881
13882 $this->rules[$type][] = $rule;
13883 $this->ruleById[$this->nextRuleId] = $rule;
13884 $rule->setType($type);
13885
13886 $this->nextRuleId++;
13887
13888 if (!isset($this->rulesByHash[$hash])) {
13889 $this->rulesByHash[$hash] = $rule;
13890 } elseif (is_array($this->rulesByHash[$hash])) {
13891 $this->rulesByHash[$hash][] = $rule;
13892 } else {
13893 $originalRule = $this->rulesByHash[$hash];
13894 $this->rulesByHash[$hash] = array($originalRule, $rule);
13895 }
13896 }
13897
13898 public function count()
13899 {
13900 return $this->nextRuleId;
13901 }
13902
13903 public function ruleById($id)
13904 {
13905 return $this->ruleById[$id];
13906 }
13907
13908 public function getRules()
13909 {
13910 return $this->rules;
13911 }
13912
13913 public function getIterator()
13914 {
13915 return new RuleSetIterator($this->getRules());
13916 }
13917
13918 public function getIteratorFor($types)
13919 {
13920 if (!is_array($types)) {
13921 $types = array($types);
13922 }
13923
13924 $allRules = $this->getRules();
13925 $rules = array();
13926
13927 foreach ($types as $type) {
13928 $rules[$type] = $allRules[$type];
13929 }
13930
13931 return new RuleSetIterator($rules);
13932 }
13933
13934 public function getIteratorWithout($types)
13935 {
13936 if (!is_array($types)) {
13937 $types = array($types);
13938 }
13939
13940 $rules = $this->getRules();
13941
13942 foreach ($types as $type) {
13943 unset($rules[$type]);
13944 }
13945
13946 return new RuleSetIterator($rules);
13947 }
13948
13949 public function getTypes()
13950 {
13951 $types = self::$types;
13952 unset($types[255]);
13953
13954 return array_keys($types);
13955 }
13956
13957 public function getPrettyString(Pool $pool = null)
13958 {
13959 $string = "\n";
13960 foreach ($this->rules as $type => $rules) {
13961 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
13962 foreach ($rules as $rule) {
13963 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
13964 }
13965 $string .= "\n\n";
13966 }
13967
13968 return $string;
13969 }
13970
13971 public function __toString()
13972 {
13973 return $this->getPrettyString(null);
13974 }
13975 }
13976 <?php
13977
13978
13979
13980
13981
13982
13983
13984
13985
13986
13987
13988 namespace Composer\DependencyResolver;
13989
13990 use Composer\Package\PackageInterface;
13991 use Composer\Package\AliasPackage;
13992 use Composer\Repository\PlatformRepository;
13993
13994
13995
13996
13997 class RuleSetGenerator
13998 {
13999 protected $policy;
14000 protected $pool;
14001 protected $rules;
14002 protected $jobs;
14003 protected $installedMap;
14004 protected $allowListedMap;
14005 protected $addedMap;
14006 protected $conflictAddedMap;
14007 protected $addedPackages;
14008 protected $addedPackagesByNames;
14009
14010 public function __construct(PolicyInterface $policy, Pool $pool)
14011 {
14012 $this->policy = $policy;
14013 $this->pool = $pool;
14014 }
14015
14016
14017
14018
14019
14020
14021
14022
14023
14024
14025
14026
14027
14028
14029
14030 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
14031 {
14032 $literals = array(-$package->id);
14033
14034 foreach ($providers as $provider) {
14035
14036 if ($provider === $package) {
14037 return null;
14038 }
14039 $literals[] = $provider->id;
14040 }
14041
14042 return new GenericRule($literals, $reason, $reasonData);
14043 }
14044
14045
14046
14047
14048
14049
14050
14051
14052
14053
14054
14055
14056
14057 protected function createInstallOneOfRule(array $packages, $reason, $job)
14058 {
14059 $literals = array();
14060 foreach ($packages as $package) {
14061 $literals[] = $package->id;
14062 }
14063
14064 return new GenericRule($literals, $reason, $job['packageName'], $job);
14065 }
14066
14067
14068
14069
14070
14071
14072
14073
14074
14075
14076
14077
14078 protected function createRemoveRule(PackageInterface $package, $reason, $job)
14079 {
14080 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
14081 }
14082
14083
14084
14085
14086
14087
14088
14089
14090
14091
14092
14093
14094
14095
14096
14097 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
14098 {
14099
14100 if ($issuer === $provider) {
14101 return null;
14102 }
14103
14104 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
14105 }
14106
14107
14108
14109
14110
14111
14112
14113
14114
14115
14116 private function addRule($type, Rule $newRule = null)
14117 {
14118 if (!$newRule) {
14119 return;
14120 }
14121
14122 $this->rules->add($newRule, $type);
14123 }
14124
14125 protected function allowListFromPackage(PackageInterface $package)
14126 {
14127
14128 $this->whitelistFromPackage($package);
14129 }
14130
14131
14132
14133
14134 protected function whitelistFromPackage(PackageInterface $package)
14135 {
14136 $workQueue = new \SplQueue;
14137 $workQueue->enqueue($package);
14138
14139 while (!$workQueue->isEmpty()) {
14140 $package = $workQueue->dequeue();
14141 if (isset($this->allowListedMap[$package->id])) {
14142 continue;
14143 }
14144
14145 $this->allowListedMap[$package->id] = true;
14146
14147 foreach ($package->getRequires() as $link) {
14148 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
14149
14150 foreach ($possibleRequires as $require) {
14151 $workQueue->enqueue($require);
14152 }
14153 }
14154
14155 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
14156
14157 foreach ($obsoleteProviders as $provider) {
14158 if ($provider === $package) {
14159 continue;
14160 }
14161
14162 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
14163 $workQueue->enqueue($provider);
14164 }
14165 }
14166 }
14167 }
14168
14169 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
14170 {
14171 $workQueue = new \SplQueue;
14172 $workQueue->enqueue($package);
14173
14174 while (!$workQueue->isEmpty()) {
14175
14176 $package = $workQueue->dequeue();
14177 if (isset($this->addedMap[$package->id])) {
14178 continue;
14179 }
14180
14181 $this->addedMap[$package->id] = true;
14182
14183 $this->addedPackages[] = $package;
14184 foreach ($package->getNames() as $name) {
14185 $this->addedPackagesByNames[$name][] = $package;
14186 }
14187
14188 foreach ($package->getRequires() as $link) {
14189 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
14190 continue;
14191 }
14192
14193 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14194
14195 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
14196
14197 foreach ($possibleRequires as $require) {
14198 $workQueue->enqueue($require);
14199 }
14200 }
14201
14202 $packageName = $package->getName();
14203 $obsoleteProviders = $this->pool->whatProvides($packageName, null);
14204
14205 foreach ($obsoleteProviders as $provider) {
14206 if ($provider === $package) {
14207 continue;
14208 }
14209
14210 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
14211 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
14212 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
14213 $reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
14214 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
14215 }
14216 }
14217 }
14218 }
14219
14220 protected function addConflictRules($ignorePlatformReqs = false)
14221 {
14222
14223 foreach ($this->addedPackages as $package) {
14224 foreach ($package->getConflicts() as $link) {
14225 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
14226 continue;
14227 }
14228
14229 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
14230 continue;
14231 }
14232
14233
14234 foreach ($this->addedPackagesByNames[$link->getTarget()] as $possibleConflict) {
14235 $conflictMatch = $this->pool->match($possibleConflict, $link->getTarget(), $link->getConstraint(), true);
14236
14237 if ($conflictMatch === Pool::MATCH || $conflictMatch === Pool::MATCH_REPLACE) {
14238 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $possibleConflict, Rule::RULE_PACKAGE_CONFLICT, $link));
14239 }
14240
14241 }
14242 }
14243
14244
14245 $isInstalled = isset($this->installedMap[$package->id]);
14246
14247 foreach ($package->getReplaces() as $link) {
14248 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
14249 continue;
14250 }
14251
14252
14253 foreach ($this->addedPackagesByNames[$link->getTarget()] as $provider) {
14254 if ($provider === $package) {
14255 continue;
14256 }
14257
14258 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
14259 $reason = $isInstalled ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
14260 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
14261 }
14262 }
14263 }
14264 }
14265 }
14266
14267 protected function obsoleteImpossibleForAlias($package, $provider)
14268 {
14269 $packageIsAlias = $package instanceof AliasPackage;
14270 $providerIsAlias = $provider instanceof AliasPackage;
14271
14272 $impossible = (
14273 ($packageIsAlias && $package->getAliasOf() === $provider) ||
14274 ($providerIsAlias && $provider->getAliasOf() === $package) ||
14275 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
14276 );
14277
14278 return $impossible;
14279 }
14280
14281 protected function allowListFromJobs()
14282 {
14283
14284 $this->whitelistFromJobs();
14285 }
14286
14287
14288
14289
14290 protected function whitelistFromJobs()
14291 {
14292 foreach ($this->jobs as $job) {
14293 switch ($job['cmd']) {
14294 case 'install':
14295 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
14296 foreach ($packages as $package) {
14297 $this->allowListFromPackage($package);
14298 }
14299 break;
14300 }
14301 }
14302 }
14303
14304 protected function addRulesForJobs($ignorePlatformReqs)
14305 {
14306 foreach ($this->jobs as $job) {
14307 switch ($job['cmd']) {
14308 case 'install':
14309 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
14310 break;
14311 }
14312
14313 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14314 if ($packages) {
14315 foreach ($packages as $package) {
14316 if (!isset($this->installedMap[$package->id])) {
14317 $this->addRulesForPackage($package, $ignorePlatformReqs);
14318 }
14319 }
14320
14321 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
14322 $this->addRule(RuleSet::TYPE_JOB, $rule);
14323 }
14324 break;
14325 case 'remove':
14326
14327
14328 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14329 foreach ($packages as $package) {
14330 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
14331 $this->addRule(RuleSet::TYPE_JOB, $rule);
14332 }
14333 break;
14334 }
14335 }
14336 }
14337
14338 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
14339 {
14340 $this->jobs = $jobs;
14341 $this->rules = new RuleSet;
14342 $this->installedMap = $installedMap;
14343
14344 $this->allowListedMap = array();
14345 foreach ($this->installedMap as $package) {
14346 $this->allowListFromPackage($package);
14347 }
14348 $this->allowListFromJobs();
14349
14350 $this->pool->setAllowList($this->allowListedMap);
14351
14352 $this->addedMap = array();
14353 $this->conflictAddedMap = array();
14354 $this->addedPackages = array();
14355 $this->addedPackagesByNames = array();
14356 foreach ($this->installedMap as $package) {
14357 $this->addRulesForPackage($package, $ignorePlatformReqs);
14358 }
14359
14360 $this->addRulesForJobs($ignorePlatformReqs);
14361
14362 $this->addConflictRules($ignorePlatformReqs);
14363
14364
14365 $this->addedPackages = $this->addedPackagesByNames = null;
14366
14367 return $this->rules;
14368 }
14369 }
14370 <?php
14371
14372
14373
14374
14375
14376
14377
14378
14379
14380
14381
14382 namespace Composer\DependencyResolver;
14383
14384
14385
14386
14387 class RuleSetIterator implements \Iterator
14388 {
14389 protected $rules;
14390 protected $types;
14391
14392 protected $currentOffset;
14393 protected $currentType;
14394 protected $currentTypeOffset;
14395
14396 public function __construct(array $rules)
14397 {
14398 $this->rules = $rules;
14399 $this->types = array_keys($rules);
14400 sort($this->types);
14401
14402 $this->rewind();
14403 }
14404
14405 public function current()
14406 {
14407 return $this->rules[$this->currentType][$this->currentOffset];
14408 }
14409
14410 public function key()
14411 {
14412 return $this->currentType;
14413 }
14414
14415 public function next()
14416 {
14417 $this->currentOffset++;
14418
14419 if (!isset($this->rules[$this->currentType])) {
14420 return;
14421 }
14422
14423 if ($this->currentOffset >= count($this->rules[$this->currentType])) {
14424 $this->currentOffset = 0;
14425
14426 do {
14427 $this->currentTypeOffset++;
14428
14429 if (!isset($this->types[$this->currentTypeOffset])) {
14430 $this->currentType = -1;
14431 break;
14432 }
14433
14434 $this->currentType = $this->types[$this->currentTypeOffset];
14435 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
14436 }
14437 }
14438
14439 public function rewind()
14440 {
14441 $this->currentOffset = 0;
14442
14443 $this->currentTypeOffset = -1;
14444 $this->currentType = -1;
14445
14446 do {
14447 $this->currentTypeOffset++;
14448
14449 if (!isset($this->types[$this->currentTypeOffset])) {
14450 $this->currentType = -1;
14451 break;
14452 }
14453
14454 $this->currentType = $this->types[$this->currentTypeOffset];
14455 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
14456 }
14457
14458 public function valid()
14459 {
14460 return isset($this->rules[$this->currentType])
14461 && isset($this->rules[$this->currentType][$this->currentOffset]);
14462 }
14463 }
14464 <?php
14465
14466
14467
14468
14469
14470
14471
14472
14473
14474
14475
14476 namespace Composer\DependencyResolver;
14477
14478
14479
14480
14481
14482
14483
14484
14485
14486 class RuleWatchChain extends \SplDoublyLinkedList
14487 {
14488 protected $offset = 0;
14489
14490
14491
14492
14493
14494
14495 public function seek($offset)
14496 {
14497 $this->rewind();
14498 for ($i = 0; $i < $offset; $i++, $this->next());
14499 }
14500
14501
14502
14503
14504
14505
14506
14507
14508
14509 public function remove()
14510 {
14511 $offset = $this->key();
14512 $this->offsetUnset($offset);
14513 $this->seek($offset);
14514 }
14515 }
14516 <?php
14517
14518
14519
14520
14521
14522
14523
14524
14525
14526
14527
14528 namespace Composer\DependencyResolver;
14529
14530
14531
14532
14533
14534
14535
14536
14537
14538
14539
14540 class RuleWatchGraph
14541 {
14542 protected $watchChains = array();
14543
14544
14545
14546
14547
14548
14549
14550
14551
14552
14553
14554
14555
14556 public function insert(RuleWatchNode $node)
14557 {
14558 if ($node->getRule()->isAssertion()) {
14559 return;
14560 }
14561
14562 foreach (array($node->watch1, $node->watch2) as $literal) {
14563 if (!isset($this->watchChains[$literal])) {
14564 $this->watchChains[$literal] = new RuleWatchChain;
14565 }
14566
14567 $this->watchChains[$literal]->unshift($node);
14568 }
14569 }
14570
14571
14572
14573
14574
14575
14576
14577
14578
14579
14580
14581
14582
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592
14593
14594 public function propagateLiteral($decidedLiteral, $level, $decisions)
14595 {
14596
14597
14598
14599 $literal = -$decidedLiteral;
14600
14601 if (!isset($this->watchChains[$literal])) {
14602 return null;
14603 }
14604
14605 $chain = $this->watchChains[$literal];
14606
14607 $chain->rewind();
14608 while ($chain->valid()) {
14609 $node = $chain->current();
14610 $otherWatch = $node->getOtherWatch($literal);
14611
14612 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
14613 $ruleLiterals = $node->getRule()->getLiterals();
14614
14615 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
14616 return $literal !== $ruleLiteral &&
14617 $otherWatch !== $ruleLiteral &&
14618 !$decisions->conflict($ruleLiteral);
14619 });
14620
14621 if ($alternativeLiterals) {
14622 reset($alternativeLiterals);
14623 $this->moveWatch($literal, current($alternativeLiterals), $node);
14624 continue;
14625 }
14626
14627 if ($decisions->conflict($otherWatch)) {
14628 return $node->getRule();
14629 }
14630
14631 $decisions->decide($otherWatch, $level, $node->getRule());
14632 }
14633
14634 $chain->next();
14635 }
14636
14637 return null;
14638 }
14639
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649 protected function moveWatch($fromLiteral, $toLiteral, $node)
14650 {
14651 if (!isset($this->watchChains[$toLiteral])) {
14652 $this->watchChains[$toLiteral] = new RuleWatchChain;
14653 }
14654
14655 $node->moveWatch($fromLiteral, $toLiteral);
14656 $this->watchChains[$fromLiteral]->remove();
14657 $this->watchChains[$toLiteral]->unshift($node);
14658 }
14659 }
14660 <?php
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672 namespace Composer\DependencyResolver;
14673
14674
14675
14676
14677
14678
14679
14680
14681 class RuleWatchNode
14682 {
14683 public $watch1;
14684 public $watch2;
14685
14686 protected $rule;
14687
14688
14689
14690
14691
14692
14693 public function __construct($rule)
14694 {
14695 $this->rule = $rule;
14696
14697 $literals = $rule->getLiterals();
14698
14699 $literalCount = count($literals);
14700 $this->watch1 = $literalCount > 0 ? $literals[0] : 0;
14701 $this->watch2 = $literalCount > 1 ? $literals[1] : 0;
14702 }
14703
14704
14705
14706
14707
14708
14709
14710
14711
14712 public function watch2OnHighest(Decisions $decisions)
14713 {
14714 $literals = $this->rule->getLiterals();
14715
14716
14717 if (count($literals) < 3) {
14718 return;
14719 }
14720
14721 $watchLevel = 0;
14722
14723 foreach ($literals as $literal) {
14724 $level = $decisions->decisionLevel($literal);
14725
14726 if ($level > $watchLevel) {
14727 $this->watch2 = $literal;
14728 $watchLevel = $level;
14729 }
14730 }
14731 }
14732
14733
14734
14735
14736
14737
14738 public function getRule()
14739 {
14740 return $this->rule;
14741 }
14742
14743
14744
14745
14746
14747
14748
14749 public function getOtherWatch($literal)
14750 {
14751 if ($this->watch1 == $literal) {
14752 return $this->watch2;
14753 }
14754
14755 return $this->watch1;
14756 }
14757
14758
14759
14760
14761
14762
14763
14764 public function moveWatch($from, $to)
14765 {
14766 if ($this->watch1 == $from) {
14767 $this->watch1 = $to;
14768 } else {
14769 $this->watch2 = $to;
14770 }
14771 }
14772 }
14773 <?php
14774
14775
14776
14777
14778
14779
14780
14781
14782
14783
14784
14785 namespace Composer\DependencyResolver;
14786
14787 use Composer\IO\IOInterface;
14788 use Composer\Repository\RepositoryInterface;
14789 use Composer\Repository\PlatformRepository;
14790
14791
14792
14793
14794 class Solver
14795 {
14796 const BRANCH_LITERALS = 0;
14797 const BRANCH_LEVEL = 1;
14798
14799
14800 protected $policy;
14801
14802 protected $pool;
14803
14804 protected $installed;
14805
14806 protected $rules;
14807
14808 protected $ruleSetGenerator;
14809
14810 protected $jobs;
14811
14812
14813 protected $updateMap = array();
14814
14815 protected $watchGraph;
14816
14817 protected $decisions;
14818
14819 protected $installedMap;
14820
14821
14822 protected $propagateIndex;
14823
14824 protected $branches = array();
14825
14826 protected $problems = array();
14827
14828 protected $learnedPool = array();
14829
14830 protected $learnedWhy = array();
14831
14832
14833 public $testFlagLearnedPositiveLiteral = false;
14834
14835
14836 protected $io;
14837
14838
14839
14840
14841
14842
14843
14844 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
14845 {
14846 $this->io = $io;
14847 $this->policy = $policy;
14848 $this->pool = $pool;
14849 $this->installed = $installed;
14850 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
14851 }
14852
14853
14854
14855
14856 public function getRuleSetSize()
14857 {
14858 return count($this->rules);
14859 }
14860
14861
14862
14863 private function makeAssertionRuleDecisions()
14864 {
14865 $decisionStart = count($this->decisions) - 1;
14866
14867 $rulesCount = count($this->rules);
14868 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
14869 $rule = $this->rules->ruleById[$ruleIndex];
14870
14871 if (!$rule->isAssertion() || $rule->isDisabled()) {
14872 continue;
14873 }
14874
14875 $literals = $rule->getLiterals();
14876 $literal = $literals[0];
14877
14878 if (!$this->decisions->decided($literal)) {
14879 $this->decisions->decide($literal, 1, $rule);
14880 continue;
14881 }
14882
14883 if ($this->decisions->satisfy($literal)) {
14884 continue;
14885 }
14886
14887
14888 if (RuleSet::TYPE_LEARNED === $rule->getType()) {
14889 $rule->disable();
14890 continue;
14891 }
14892
14893 $conflict = $this->decisions->decisionRule($literal);
14894
14895 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
14896 $problem = new Problem($this->pool);
14897
14898 $problem->addRule($rule);
14899 $problem->addRule($conflict);
14900 $this->disableProblem($rule);
14901 $this->problems[] = $problem;
14902 continue;
14903 }
14904
14905
14906 $problem = new Problem($this->pool);
14907 $problem->addRule($rule);
14908 $problem->addRule($conflict);
14909
14910
14911
14912 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
14913 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
14914 continue;
14915 }
14916
14917 $assertRuleLiterals = $assertRule->getLiterals();
14918 $assertRuleLiteral = $assertRuleLiterals[0];
14919
14920 if (abs($literal) !== abs($assertRuleLiteral)) {
14921 continue;
14922 }
14923
14924 $problem->addRule($assertRule);
14925 $this->disableProblem($assertRule);
14926 }
14927 $this->problems[] = $problem;
14928
14929 $this->decisions->resetToOffset($decisionStart);
14930 $ruleIndex = -1;
14931 }
14932 }
14933
14934 protected function setupInstalledMap()
14935 {
14936 $this->installedMap = array();
14937 foreach ($this->installed->getPackages() as $package) {
14938 $this->installedMap[$package->id] = $package;
14939 }
14940 }
14941
14942
14943
14944
14945 protected function checkForRootRequireProblems($ignorePlatformReqs)
14946 {
14947 foreach ($this->jobs as $job) {
14948 switch ($job['cmd']) {
14949 case 'update':
14950 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14951 foreach ($packages as $package) {
14952 if (isset($this->installedMap[$package->id])) {
14953 $this->updateMap[$package->id] = true;
14954 }
14955 }
14956 break;
14957
14958 case 'update-all':
14959 foreach ($this->installedMap as $package) {
14960 $this->updateMap[$package->id] = true;
14961 }
14962 break;
14963
14964 case 'install':
14965 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
14966 break;
14967 }
14968
14969 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
14970 $problem = new Problem($this->pool);
14971 $problem->addRule(new GenericRule(array(), null, null, $job));
14972 $this->problems[] = $problem;
14973 }
14974 break;
14975 }
14976 }
14977 }
14978
14979
14980
14981
14982
14983
14984 public function solve(Request $request, $ignorePlatformReqs = false)
14985 {
14986 $this->jobs = $request->getJobs();
14987
14988 $this->setupInstalledMap();
14989 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
14990 $this->checkForRootRequireProblems($ignorePlatformReqs);
14991 $this->decisions = new Decisions($this->pool);
14992 $this->watchGraph = new RuleWatchGraph;
14993
14994 foreach ($this->rules as $rule) {
14995 $this->watchGraph->insert(new RuleWatchNode($rule));
14996 }
14997
14998
14999 $this->makeAssertionRuleDecisions();
15000
15001 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
15002 $before = microtime(true);
15003 $this->runSat(true);
15004 $this->io->writeError('', true, IOInterface::DEBUG);
15005 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
15006
15007
15008 foreach ($this->installedMap as $packageId => $void) {
15009 if ($this->decisions->undecided($packageId)) {
15010 $this->decisions->decide(-$packageId, 1, null);
15011 }
15012 }
15013
15014 if ($this->problems) {
15015 throw new SolverProblemsException($this->problems, $this->installedMap);
15016 }
15017
15018 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
15019
15020 return $transaction->getOperations();
15021 }
15022
15023
15024
15025
15026
15027
15028
15029
15030
15031
15032 protected function propagate($level)
15033 {
15034 while ($this->decisions->validOffset($this->propagateIndex)) {
15035 $decision = $this->decisions->atOffset($this->propagateIndex);
15036
15037 $conflict = $this->watchGraph->propagateLiteral(
15038 $decision[Decisions::DECISION_LITERAL],
15039 $level,
15040 $this->decisions
15041 );
15042
15043 $this->propagateIndex++;
15044
15045 if ($conflict) {
15046 return $conflict;
15047 }
15048 }
15049
15050 return null;
15051 }
15052
15053
15054
15055
15056
15057
15058 private function revert($level)
15059 {
15060 while (!$this->decisions->isEmpty()) {
15061 $literal = $this->decisions->lastLiteral();
15062
15063 if ($this->decisions->undecided($literal)) {
15064 break;
15065 }
15066
15067 $decisionLevel = $this->decisions->decisionLevel($literal);
15068
15069 if ($decisionLevel <= $level) {
15070 break;
15071 }
15072
15073 $this->decisions->revertLast();
15074 $this->propagateIndex = count($this->decisions);
15075 }
15076
15077 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
15078 array_pop($this->branches);
15079 }
15080 }
15081
15082
15083
15084
15085
15086
15087
15088
15089
15090
15091
15092
15093
15094
15095
15096
15097
15098
15099
15100
15101 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
15102 {
15103 $level++;
15104
15105 $this->decisions->decide($literal, $level, $rule);
15106
15107 while (true) {
15108 $rule = $this->propagate($level);
15109
15110 if (!$rule) {
15111 break;
15112 }
15113
15114 if ($level == 1) {
15115 return $this->analyzeUnsolvable($rule, $disableRules);
15116 }
15117
15118
15119 list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
15120
15121 if ($newLevel <= 0 || $newLevel >= $level) {
15122 throw new SolverBugException(
15123 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
15124 );
15125 } elseif (!$newRule) {
15126 throw new SolverBugException(
15127 "No rule was learned from analyzing $rule at level $level."
15128 );
15129 }
15130
15131 $level = $newLevel;
15132
15133 $this->revert($level);
15134
15135 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
15136
15137 $this->learnedWhy[spl_object_hash($newRule)] = $why;
15138
15139 $ruleNode = new RuleWatchNode($newRule);
15140 $ruleNode->watch2OnHighest($this->decisions);
15141 $this->watchGraph->insert($ruleNode);
15142
15143 $this->decisions->decide($learnLiteral, $level, $newRule);
15144 }
15145
15146 return $level;
15147 }
15148
15149
15150
15151
15152
15153
15154
15155
15156 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
15157 {
15158
15159 $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
15160
15161 $selectedLiteral = array_shift($literals);
15162
15163
15164 if (count($literals)) {
15165 $this->branches[] = array($literals, $level);
15166 }
15167
15168 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
15169 }
15170
15171
15172
15173
15174
15175
15176 protected function analyze($level, Rule $rule)
15177 {
15178 $analyzedRule = $rule;
15179 $ruleLevel = 1;
15180 $num = 0;
15181 $l1num = 0;
15182 $seen = array();
15183 $learnedLiterals = array(null);
15184
15185 $decisionId = count($this->decisions);
15186
15187 $this->learnedPool[] = array();
15188
15189 while (true) {
15190 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
15191
15192 foreach ($rule->getLiterals() as $literal) {
15193
15194 if ($this->decisions->satisfy($literal)) {
15195 continue;
15196 }
15197
15198 if (isset($seen[abs($literal)])) {
15199 continue;
15200 }
15201 $seen[abs($literal)] = true;
15202
15203 $l = $this->decisions->decisionLevel($literal);
15204
15205 if (1 === $l) {
15206 $l1num++;
15207 } elseif ($level === $l) {
15208 $num++;
15209 } else {
15210
15211 $learnedLiterals[] = $literal;
15212
15213 if ($l > $ruleLevel) {
15214 $ruleLevel = $l;
15215 }
15216 }
15217 }
15218
15219 $l1retry = true;
15220 while ($l1retry) {
15221 $l1retry = false;
15222
15223 if (!$num && !--$l1num) {
15224
15225 break 2;
15226 }
15227
15228 while (true) {
15229 if ($decisionId <= 0) {
15230 throw new SolverBugException(
15231 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
15232 );
15233 }
15234
15235 $decisionId--;
15236
15237 $decision = $this->decisions->atOffset($decisionId);
15238 $literal = $decision[Decisions::DECISION_LITERAL];
15239
15240 if (isset($seen[abs($literal)])) {
15241 break;
15242 }
15243 }
15244
15245 unset($seen[abs($literal)]);
15246
15247 if ($num && 0 === --$num) {
15248 if ($literal < 0) {
15249 $this->testFlagLearnedPositiveLiteral = true;
15250 }
15251 $learnedLiterals[0] = -$literal;
15252
15253 if (!$l1num) {
15254 break 2;
15255 }
15256
15257 foreach ($learnedLiterals as $i => $learnedLiteral) {
15258 if ($i !== 0) {
15259 unset($seen[abs($learnedLiteral)]);
15260 }
15261 }
15262
15263 $l1num++;
15264 $l1retry = true;
15265 }
15266 }
15267
15268 $decision = $this->decisions->atOffset($decisionId);
15269 $rule = $decision[Decisions::DECISION_REASON];
15270 }
15271
15272 $why = count($this->learnedPool) - 1;
15273
15274 if (!$learnedLiterals[0]) {
15275 throw new SolverBugException(
15276 "Did not find a learnable literal in analyzed rule $analyzedRule."
15277 );
15278 }
15279
15280 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
15281
15282 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
15283 }
15284
15285
15286
15287
15288
15289 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
15290 {
15291 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
15292 $why = spl_object_hash($conflictRule);
15293 $learnedWhy = $this->learnedWhy[$why];
15294 $problemRules = $this->learnedPool[$learnedWhy];
15295
15296 foreach ($problemRules as $problemRule) {
15297 $this->analyzeUnsolvableRule($problem, $problemRule);
15298 }
15299
15300 return;
15301 }
15302
15303 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
15304
15305 return;
15306 }
15307
15308 $problem->nextSection();
15309 $problem->addRule($conflictRule);
15310 }
15311
15312
15313
15314
15315
15316
15317 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
15318 {
15319 $problem = new Problem($this->pool);
15320 $problem->addRule($conflictRule);
15321
15322 $this->analyzeUnsolvableRule($problem, $conflictRule);
15323
15324 $this->problems[] = $problem;
15325
15326 $seen = array();
15327 $literals = $conflictRule->getLiterals();
15328
15329 foreach ($literals as $literal) {
15330
15331 if ($this->decisions->satisfy($literal)) {
15332 continue;
15333 }
15334 $seen[abs($literal)] = true;
15335 }
15336
15337 foreach ($this->decisions as $decision) {
15338 $literal = $decision[Decisions::DECISION_LITERAL];
15339
15340
15341 if (!isset($seen[abs($literal)])) {
15342 continue;
15343 }
15344
15345 $why = $decision[Decisions::DECISION_REASON];
15346
15347 $problem->addRule($why);
15348 $this->analyzeUnsolvableRule($problem, $why);
15349
15350 $literals = $why->getLiterals();
15351
15352 foreach ($literals as $literal) {
15353
15354 if ($this->decisions->satisfy($literal)) {
15355 continue;
15356 }
15357 $seen[abs($literal)] = true;
15358 }
15359 }
15360
15361 if ($disableRules) {
15362 foreach ($this->problems[count($this->problems) - 1] as $reason) {
15363 $this->disableProblem($reason['rule']);
15364 }
15365
15366 $this->resetSolver();
15367
15368 return 1;
15369 }
15370
15371 return 0;
15372 }
15373
15374
15375
15376
15377 private function disableProblem(Rule $why)
15378 {
15379 $job = $why->getJob();
15380
15381 if (!$job) {
15382 $why->disable();
15383
15384 return;
15385 }
15386
15387
15388 foreach ($this->rules as $rule) {
15389
15390 if ($job === $rule->getJob()) {
15391 $rule->disable();
15392 }
15393 }
15394 }
15395
15396 private function resetSolver()
15397 {
15398 $this->decisions->reset();
15399
15400 $this->propagateIndex = 0;
15401 $this->branches = array();
15402
15403 $this->enableDisableLearnedRules();
15404 $this->makeAssertionRuleDecisions();
15405 }
15406
15407
15408
15409
15410
15411
15412
15413
15414 private function enableDisableLearnedRules()
15415 {
15416 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
15417 $why = $this->learnedWhy[spl_object_hash($rule)];
15418 $problemRules = $this->learnedPool[$why];
15419
15420 $foundDisabled = false;
15421 foreach ($problemRules as $problemRule) {
15422 if ($problemRule->isDisabled()) {
15423 $foundDisabled = true;
15424 break;
15425 }
15426 }
15427
15428 if ($foundDisabled && $rule->isEnabled()) {
15429 $rule->disable();
15430 } elseif (!$foundDisabled && $rule->isDisabled()) {
15431 $rule->enable();
15432 }
15433 }
15434 }
15435
15436
15437
15438
15439 private function runSat($disableRules = true)
15440 {
15441 $this->propagateIndex = 0;
15442
15443
15444
15445
15446
15447
15448
15449
15450
15451
15452
15453 $decisionQueue = array();
15454
15455
15456
15457 $disableRules = array();
15458
15459 $level = 1;
15460 $systemLevel = $level + 1;
15461
15462 while (true) {
15463 if (1 === $level) {
15464 $conflictRule = $this->propagate($level);
15465 if (null !== $conflictRule) {
15466 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
15467 continue;
15468 }
15469
15470 return;
15471 }
15472 }
15473
15474
15475 if ($level < $systemLevel) {
15476 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
15477 foreach ($iterator as $rule) {
15478 if ($rule->isEnabled()) {
15479 $decisionQueue = array();
15480 $noneSatisfied = true;
15481
15482 foreach ($rule->getLiterals() as $literal) {
15483 if ($this->decisions->satisfy($literal)) {
15484 $noneSatisfied = false;
15485 break;
15486 }
15487 if ($literal > 0 && $this->decisions->undecided($literal)) {
15488 $decisionQueue[] = $literal;
15489 }
15490 }
15491
15492 if ($noneSatisfied && count($decisionQueue)) {
15493
15494
15495 if (count($this->installed) != count($this->updateMap)) {
15496 $prunedQueue = array();
15497 foreach ($decisionQueue as $literal) {
15498 if (isset($this->installedMap[abs($literal)])) {
15499 $prunedQueue[] = $literal;
15500 if (isset($this->updateMap[abs($literal)])) {
15501 $prunedQueue = $decisionQueue;
15502 break;
15503 }
15504 }
15505 }
15506 $decisionQueue = $prunedQueue;
15507 }
15508 }
15509
15510 if ($noneSatisfied && count($decisionQueue)) {
15511 $oLevel = $level;
15512 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
15513
15514 if (0 === $level) {
15515 return;
15516 }
15517 if ($level <= $oLevel) {
15518 break;
15519 }
15520 }
15521 }
15522 }
15523
15524 $systemLevel = $level + 1;
15525
15526
15527 $iterator->next();
15528 if ($iterator->valid()) {
15529 continue;
15530 }
15531 }
15532
15533 if ($level < $systemLevel) {
15534 $systemLevel = $level;
15535 }
15536
15537 $rulesCount = count($this->rules);
15538 $pass = 1;
15539
15540 $this->io->writeError('Looking at all rules.', true, IOInterface::DEBUG);
15541 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
15542 if ($i == $rulesCount) {
15543 if (1 === $pass) {
15544 $this->io->writeError("Something's changed, looking at all rules again (pass #$pass)", false, IOInterface::DEBUG);
15545 } else {
15546 $this->io->overwriteError("Something's changed, looking at all rules again (pass #$pass)", false, null, IOInterface::DEBUG);
15547 }
15548
15549 $i = 0;
15550 $pass++;
15551 }
15552
15553 $rule = $this->rules->ruleById[$i];
15554 $literals = $rule->getLiterals();
15555
15556 if ($rule->isDisabled()) {
15557 continue;
15558 }
15559
15560 $decisionQueue = array();
15561
15562
15563
15564
15565
15566
15567
15568 foreach ($literals as $literal) {
15569 if ($literal <= 0) {
15570 if (!$this->decisions->decidedInstall($literal)) {
15571 continue 2; 
15572 }
15573 } else {
15574 if ($this->decisions->decidedInstall($literal)) {
15575 continue 2; 
15576 }
15577 if ($this->decisions->undecided($literal)) {
15578 $decisionQueue[] = $literal;
15579 }
15580 }
15581 }
15582
15583
15584 if (count($decisionQueue) < 2) {
15585 continue;
15586 }
15587
15588 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
15589
15590 if (0 === $level) {
15591 return;
15592 }
15593
15594
15595 $rulesCount = count($this->rules);
15596 $n = -1;
15597 }
15598
15599 if ($level < $systemLevel) {
15600 continue;
15601 }
15602
15603
15604 if (count($this->branches)) {
15605 $lastLiteral = null;
15606 $lastLevel = null;
15607 $lastBranchIndex = 0;
15608 $lastBranchOffset = 0;
15609
15610 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
15611 list($literals, $l) = $this->branches[$i];
15612
15613 foreach ($literals as $offset => $literal) {
15614 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
15615 $lastLiteral = $literal;
15616 $lastBranchIndex = $i;
15617 $lastBranchOffset = $offset;
15618 $lastLevel = $l;
15619 }
15620 }
15621 }
15622
15623 if ($lastLiteral) {
15624 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
15625
15626 $level = $lastLevel;
15627 $this->revert($level);
15628
15629 $why = $this->decisions->lastReason();
15630
15631 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
15632
15633 if ($level == 0) {
15634 return;
15635 }
15636
15637 continue;
15638 }
15639 }
15640
15641 break;
15642 }
15643 }
15644 }
15645 <?php
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657 namespace Composer\DependencyResolver;
15658
15659
15660
15661
15662 class SolverBugException extends \RuntimeException
15663 {
15664 public function __construct($message)
15665 {
15666 parent::__construct(
15667 $message."\nThis exception was most likely caused by a bug in Composer.\n".
15668 "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"
15669 );
15670 }
15671 }
15672 <?php
15673
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684 namespace Composer\DependencyResolver;
15685
15686 use Composer\Util\IniHelper;
15687
15688
15689
15690
15691 class SolverProblemsException extends \RuntimeException
15692 {
15693 protected $problems;
15694 protected $installedMap;
15695
15696 public function __construct(array $problems, array $installedMap)
15697 {
15698 $this->problems = $problems;
15699 $this->installedMap = $installedMap;
15700
15701 parent::__construct($this->createMessage(), 2);
15702 }
15703
15704 protected function createMessage()
15705 {
15706 $text = "\n";
15707 $hasExtensionProblems = false;
15708 foreach ($this->problems as $i => $problem) {
15709 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
15710
15711 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
15712 $hasExtensionProblems = true;
15713 }
15714 }
15715
15716 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
15717 $text .= "\nPotential causes:\n - This package is not installable via Composer 1.x, see <https://blog.packagist.com/deprecating-composer-1-support/>\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
15718 }
15719
15720 if ($hasExtensionProblems) {
15721 $text .= $this->createExtensionHint();
15722 }
15723
15724 return $text;
15725 }
15726
15727 public function getProblems()
15728 {
15729 return $this->problems;
15730 }
15731
15732 private function createExtensionHint()
15733 {
15734 $paths = IniHelper::getAll();
15735
15736 if (count($paths) === 1 && empty($paths[0])) {
15737 return '';
15738 }
15739
15740 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
15741 $text .= implode("\n    - ", $paths);
15742 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
15743
15744 return $text;
15745 }
15746
15747 private function hasExtensionProblems(array $reasonSets)
15748 {
15749 foreach ($reasonSets as $reasonSet) {
15750 foreach ($reasonSet as $reason) {
15751 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
15752 return true;
15753 }
15754 }
15755 }
15756
15757 return false;
15758 }
15759 }
15760 <?php
15761
15762
15763
15764
15765
15766
15767
15768
15769
15770
15771
15772 namespace Composer\DependencyResolver;
15773
15774 use Composer\Package\AliasPackage;
15775
15776
15777
15778
15779 class Transaction
15780 {
15781 protected $policy;
15782 protected $pool;
15783 protected $installedMap;
15784 protected $decisions;
15785 protected $transaction;
15786
15787 public function __construct($policy, $pool, $installedMap, $decisions)
15788 {
15789 $this->policy = $policy;
15790 $this->pool = $pool;
15791 $this->installedMap = $installedMap;
15792 $this->decisions = $decisions;
15793 $this->transaction = array();
15794 }
15795
15796 public function getOperations()
15797 {
15798 $installMeansUpdateMap = $this->findUpdates();
15799
15800 $updateMap = array();
15801 $installMap = array();
15802 $uninstallMap = array();
15803
15804 foreach ($this->decisions as $i => $decision) {
15805 $literal = $decision[Decisions::DECISION_LITERAL];
15806 $reason = $decision[Decisions::DECISION_REASON];
15807
15808 $package = $this->pool->literalToPackage($literal);
15809
15810
15811 if (($literal > 0) == isset($this->installedMap[$package->id])) {
15812 continue;
15813 }
15814
15815 if ($literal > 0) {
15816 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
15817 $source = $installMeansUpdateMap[abs($literal)];
15818
15819 $updateMap[$package->id] = array(
15820 'package' => $package,
15821 'source' => $source,
15822 'reason' => $reason,
15823 );
15824
15825
15826 unset($installMeansUpdateMap[abs($literal)]);
15827 $ignoreRemove[$source->id] = true;
15828 } else {
15829 $installMap[$package->id] = array(
15830 'package' => $package,
15831 'reason' => $reason,
15832 );
15833 }
15834 }
15835 }
15836
15837 foreach ($this->decisions as $i => $decision) {
15838 $literal = $decision[Decisions::DECISION_LITERAL];
15839 $reason = $decision[Decisions::DECISION_REASON];
15840 $package = $this->pool->literalToPackage($literal);
15841
15842 if ($literal <= 0 &&
15843 isset($this->installedMap[$package->id]) &&
15844 !isset($ignoreRemove[$package->id])) {
15845 $uninstallMap[$package->id] = array(
15846 'package' => $package,
15847 'reason' => $reason,
15848 );
15849 }
15850 }
15851
15852 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
15853
15854 return $this->transaction;
15855 }
15856
15857 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
15858 {
15859 $queue = array_map(
15860 function ($operation) {
15861 return $operation['package'];
15862 },
15863 $this->findRootPackages($installMap, $updateMap)
15864 );
15865
15866 $visited = array();
15867
15868 while (!empty($queue)) {
15869 $package = array_pop($queue);
15870 $packageId = $package->id;
15871
15872 if (!isset($visited[$packageId])) {
15873 $queue[] = $package;
15874
15875 if ($package instanceof AliasPackage) {
15876 $queue[] = $package->getAliasOf();
15877 } else {
15878 foreach ($package->getRequires() as $link) {
15879 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
15880
15881 foreach ($possibleRequires as $require) {
15882 $queue[] = $require;
15883 }
15884 }
15885 }
15886
15887 $visited[$package->id] = true;
15888 } else {
15889 if (isset($installMap[$packageId])) {
15890 $this->install(
15891 $installMap[$packageId]['package'],
15892 $installMap[$packageId]['reason']
15893 );
15894 unset($installMap[$packageId]);
15895 }
15896 if (isset($updateMap[$packageId])) {
15897 $this->update(
15898 $updateMap[$packageId]['source'],
15899 $updateMap[$packageId]['package'],
15900 $updateMap[$packageId]['reason']
15901 );
15902 unset($updateMap[$packageId]);
15903 }
15904 }
15905 }
15906
15907 foreach ($uninstallMap as $uninstall) {
15908 $this->uninstall($uninstall['package'], $uninstall['reason']);
15909 }
15910 }
15911
15912 protected function findRootPackages($installMap, $updateMap)
15913 {
15914 $packages = $installMap + $updateMap;
15915 $roots = $packages;
15916
15917 foreach ($packages as $packageId => $operation) {
15918 $package = $operation['package'];
15919
15920 if (!isset($roots[$packageId])) {
15921 continue;
15922 }
15923
15924 foreach ($package->getRequires() as $link) {
15925 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
15926
15927 foreach ($possibleRequires as $require) {
15928 if ($require !== $package) {
15929 unset($roots[$require->id]);
15930 }
15931 }
15932 }
15933 }
15934
15935 return $roots;
15936 }
15937
15938 protected function findUpdates()
15939 {
15940 $installMeansUpdateMap = array();
15941
15942 foreach ($this->decisions as $i => $decision) {
15943 $literal = $decision[Decisions::DECISION_LITERAL];
15944 $package = $this->pool->literalToPackage($literal);
15945
15946 if ($package instanceof AliasPackage) {
15947 continue;
15948 }
15949
15950
15951 if ($literal <= 0 && isset($this->installedMap[$package->id])) {
15952 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
15953
15954 $literals = array($package->id);
15955
15956 foreach ($updates as $update) {
15957 $literals[] = $update->id;
15958 }
15959
15960 foreach ($literals as $updateLiteral) {
15961 if ($updateLiteral !== $literal) {
15962 $installMeansUpdateMap[abs($updateLiteral)] = $package;
15963 }
15964 }
15965 }
15966 }
15967
15968 return $installMeansUpdateMap;
15969 }
15970
15971 protected function install($package, $reason)
15972 {
15973 if ($package instanceof AliasPackage) {
15974 return $this->markAliasInstalled($package, $reason);
15975 }
15976
15977 $this->transaction[] = new Operation\InstallOperation($package, $reason);
15978 }
15979
15980 protected function update($from, $to, $reason)
15981 {
15982 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
15983 }
15984
15985 protected function uninstall($package, $reason)
15986 {
15987 if ($package instanceof AliasPackage) {
15988 return $this->markAliasUninstalled($package, $reason);
15989 }
15990
15991 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
15992 }
15993
15994 protected function markAliasInstalled($package, $reason)
15995 {
15996 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
15997 }
15998
15999 protected function markAliasUninstalled($package, $reason)
16000 {
16001 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
16002 }
16003 }
16004 <?php
16005
16006
16007
16008
16009
16010
16011
16012
16013
16014
16015
16016 namespace Composer\Downloader;
16017
16018 use Composer\Package\PackageInterface;
16019 use Symfony\Component\Finder\Finder;
16020 use Composer\IO\IOInterface;
16021
16022
16023
16024
16025
16026
16027
16028
16029 abstract class ArchiveDownloader extends FileDownloader
16030 {
16031
16032
16033
16034
16035
16036 public function download(PackageInterface $package, $path, $output = true)
16037 {
16038 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
16039 $retries = 3;
16040 while ($retries--) {
16041 $fileName = parent::download($package, $path, $output);
16042
16043 if ($output) {
16044 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
16045 }
16046
16047 try {
16048 $this->filesystem->ensureDirectoryExists($temporaryDir);
16049 try {
16050 $this->extract($fileName, $temporaryDir);
16051 } catch (\Exception $e) {
16052
16053 parent::clearLastCacheWrite($package);
16054 throw $e;
16055 }
16056
16057 $this->filesystem->unlink($fileName);
16058
16059 $contentDir = $this->getFolderContent($temporaryDir);
16060
16061
16062 if (1 === count($contentDir) && is_dir(reset($contentDir))) {
16063 $contentDir = $this->getFolderContent((string) reset($contentDir));
16064 }
16065
16066
16067 foreach ($contentDir as $file) {
16068 $file = (string) $file;
16069 $this->filesystem->rename($file, $path . '/' . basename($file));
16070 }
16071
16072 $this->filesystem->removeDirectory($temporaryDir);
16073 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
16074 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
16075 }
16076 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
16077 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
16078 }
16079 } catch (\Exception $e) {
16080
16081 $this->filesystem->removeDirectory($path);
16082 $this->filesystem->removeDirectory($temporaryDir);
16083
16084
16085 if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
16086 $this->io->writeError('');
16087 if ($this->io->isDebug()) {
16088 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
16089 } else {
16090 $this->io->writeError('    Invalid zip file, retrying...');
16091 }
16092 usleep(500000);
16093 continue;
16094 }
16095
16096 throw $e;
16097 }
16098
16099 break;
16100 }
16101 }
16102
16103
16104
16105
16106 protected function getFileName(PackageInterface $package, $path)
16107 {
16108 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
16109 }
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119 abstract protected function extract($file, $path);
16120
16121
16122
16123
16124
16125
16126
16127 private function getFolderContent($dir)
16128 {
16129 $finder = Finder::create()
16130 ->ignoreVCS(false)
16131 ->ignoreDotFiles(false)
16132 ->notName('.DS_Store')
16133 ->depth(0)
16134 ->in($dir);
16135
16136 return iterator_to_array($finder);
16137 }
16138 }
16139 <?php
16140
16141
16142
16143
16144
16145
16146
16147
16148
16149
16150
16151 namespace Composer\Downloader;
16152
16153 use Composer\Package\PackageInterface;
16154
16155
16156
16157
16158
16159
16160 interface ChangeReportInterface
16161 {
16162
16163
16164
16165
16166
16167
16168
16169 public function getLocalChanges(PackageInterface $package, $path);
16170 }
16171 <?php
16172
16173
16174
16175
16176
16177
16178
16179
16180
16181
16182
16183 namespace Composer\Downloader;
16184
16185 use Composer\Package\PackageInterface;
16186 use Composer\IO\IOInterface;
16187 use Composer\Util\Filesystem;
16188
16189
16190
16191
16192
16193
16194 class DownloadManager
16195 {
16196 private $io;
16197 private $preferDist = false;
16198 private $preferSource = false;
16199 private $packagePreferences = array();
16200 private $filesystem;
16201 private $downloaders = array();
16202
16203
16204
16205
16206
16207
16208
16209
16210 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
16211 {
16212 $this->io = $io;
16213 $this->preferSource = $preferSource;
16214 $this->filesystem = $filesystem ?: new Filesystem();
16215 }
16216
16217
16218
16219
16220
16221
16222
16223 public function setPreferSource($preferSource)
16224 {
16225 $this->preferSource = $preferSource;
16226
16227 return $this;
16228 }
16229
16230
16231
16232
16233
16234
16235
16236 public function setPreferDist($preferDist)
16237 {
16238 $this->preferDist = $preferDist;
16239
16240 return $this;
16241 }
16242
16243
16244
16245
16246
16247
16248
16249 public function setPreferences(array $preferences)
16250 {
16251 $this->packagePreferences = $preferences;
16252
16253 return $this;
16254 }
16255
16256
16257
16258
16259
16260
16261
16262
16263 public function setOutputProgress($outputProgress)
16264 {
16265 foreach ($this->downloaders as $downloader) {
16266 $downloader->setOutputProgress($outputProgress);
16267 }
16268
16269 return $this;
16270 }
16271
16272
16273
16274
16275
16276
16277
16278
16279 public function setDownloader($type, DownloaderInterface $downloader)
16280 {
16281 $type = strtolower($type);
16282 $this->downloaders[$type] = $downloader;
16283
16284 return $this;
16285 }
16286
16287
16288
16289
16290
16291
16292
16293
16294 public function getDownloader($type)
16295 {
16296 $type = strtolower($type);
16297 if (!isset($this->downloaders[$type])) {
16298 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
16299 }
16300
16301 return $this->downloaders[$type];
16302 }
16303
16304
16305
16306
16307
16308
16309
16310
16311
16312
16313 public function getDownloaderForInstalledPackage(PackageInterface $package)
16314 {
16315 $installationSource = $package->getInstallationSource();
16316
16317 if ('metapackage' === $package->getType()) {
16318 return;
16319 }
16320
16321 if ('dist' === $installationSource) {
16322 $downloader = $this->getDownloader($package->getDistType());
16323 } elseif ('source' === $installationSource) {
16324 $downloader = $this->getDownloader($package->getSourceType());
16325 } else {
16326 throw new \InvalidArgumentException(
16327 'Package '.$package.' seems not been installed properly'
16328 );
16329 }
16330
16331 if ($installationSource !== $downloader->getInstallationSource()) {
16332 throw new \LogicException(sprintf(
16333 'Downloader "%s" is a %s type downloader and can not be used to download %s for package %s',
16334 get_class($downloader),
16335 $downloader->getInstallationSource(),
16336 $installationSource,
16337 $package
16338 ));
16339 }
16340
16341 return $downloader;
16342 }
16343
16344
16345
16346
16347
16348
16349
16350
16351
16352
16353
16354 public function download(PackageInterface $package, $targetDir, $preferSource = null)
16355 {
16356 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
16357 $sourceType = $package->getSourceType();
16358 $distType = $package->getDistType();
16359
16360 $sources = array();
16361 if ($sourceType) {
16362 $sources[] = 'source';
16363 }
16364 if ($distType) {
16365 $sources[] = 'dist';
16366 }
16367
16368 if (empty($sources)) {
16369 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
16370 }
16371
16372 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
16373 $sources = array_reverse($sources);
16374 }
16375
16376 $this->filesystem->ensureDirectoryExists($targetDir);
16377
16378 foreach ($sources as $i => $source) {
16379 if (isset($e)) {
16380 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
16381 }
16382 $package->setInstallationSource($source);
16383 try {
16384 $downloader = $this->getDownloaderForInstalledPackage($package);
16385 if ($downloader) {
16386 $downloader->download($package, $targetDir);
16387 }
16388 break;
16389 } catch (\RuntimeException $e) {
16390 if ($i === count($sources) - 1) {
16391 throw $e;
16392 }
16393
16394 $this->io->writeError(
16395 '    <warning>Failed to download '.
16396 $package->getPrettyName().
16397 ' from ' . $source . ': '.
16398 $e->getMessage().'</warning>'
16399 );
16400 }
16401 }
16402 }
16403
16404
16405
16406
16407
16408
16409
16410
16411
16412
16413 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
16414 {
16415 $downloader = $this->getDownloaderForInstalledPackage($initial);
16416 if (!$downloader) {
16417 return;
16418 }
16419
16420 $installationSource = $initial->getInstallationSource();
16421
16422 if ('dist' === $installationSource) {
16423 $initialType = $initial->getDistType();
16424 $targetType = $target->getDistType();
16425 } else {
16426 $initialType = $initial->getSourceType();
16427 $targetType = $target->getSourceType();
16428 }
16429
16430
16431 if ($target->isDev() && 'dist' === $installationSource) {
16432 $downloader->remove($initial, $targetDir);
16433 $this->download($target, $targetDir);
16434
16435 return;
16436 }
16437
16438 if ($initialType === $targetType) {
16439 $target->setInstallationSource($installationSource);
16440 try {
16441 $downloader->update($initial, $target, $targetDir);
16442
16443 return;
16444 } catch (\RuntimeException $e) {
16445 if (!$this->io->isInteractive()) {
16446 throw $e;
16447 }
16448 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
16449 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
16450 throw $e;
16451 }
16452 }
16453 }
16454
16455 $downloader->remove($initial, $targetDir);
16456 $this->download($target, $targetDir, 'source' === $installationSource);
16457 }
16458
16459
16460
16461
16462
16463
16464
16465 public function remove(PackageInterface $package, $targetDir)
16466 {
16467 $downloader = $this->getDownloaderForInstalledPackage($package);
16468 if ($downloader) {
16469 $downloader->remove($package, $targetDir);
16470 }
16471 }
16472
16473
16474
16475
16476
16477
16478
16479
16480 protected function resolvePackageInstallPreference(PackageInterface $package)
16481 {
16482 foreach ($this->packagePreferences as $pattern => $preference) {
16483 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
16484 if (preg_match($pattern, $package->getName())) {
16485 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
16486 return 'dist';
16487 }
16488
16489 return 'source';
16490 }
16491 }
16492
16493 return $package->isDev() ? 'source' : 'dist';
16494 }
16495 }
16496 <?php
16497
16498
16499
16500
16501
16502
16503
16504
16505
16506
16507
16508 namespace Composer\Downloader;
16509
16510 use Composer\Package\PackageInterface;
16511
16512
16513
16514
16515
16516
16517
16518 interface DownloaderInterface
16519 {
16520
16521
16522
16523
16524
16525 public function getInstallationSource();
16526
16527
16528
16529
16530
16531
16532
16533 public function download(PackageInterface $package, $path);
16534
16535
16536
16537
16538
16539
16540
16541
16542 public function update(PackageInterface $initial, PackageInterface $target, $path);
16543
16544
16545
16546
16547
16548
16549
16550 public function remove(PackageInterface $package, $path);
16551
16552
16553
16554
16555
16556
16557
16558 public function setOutputProgress($outputProgress);
16559 }
16560 <?php
16561
16562
16563
16564
16565
16566
16567
16568
16569
16570
16571
16572 namespace Composer\Downloader;
16573
16574 use Composer\Package\PackageInterface;
16575
16576
16577
16578
16579
16580
16581 interface DvcsDownloaderInterface
16582 {
16583
16584
16585
16586
16587
16588
16589
16590 public function getUnpushedChanges(PackageInterface $package, $path);
16591 }
16592 <?php
16593
16594
16595
16596
16597
16598
16599
16600
16601
16602
16603
16604 namespace Composer\Downloader;
16605
16606 use Composer\Config;
16607 use Composer\Cache;
16608 use Composer\Factory;
16609 use Composer\IO\IOInterface;
16610 use Composer\IO\NullIO;
16611 use Composer\Package\Comparer\Comparer;
16612 use Composer\Package\PackageInterface;
16613 use Composer\Package\Version\VersionParser;
16614 use Composer\Plugin\PluginEvents;
16615 use Composer\Plugin\PreFileDownloadEvent;
16616 use Composer\EventDispatcher\EventDispatcher;
16617 use Composer\Util\Filesystem;
16618 use Composer\Util\RemoteFilesystem;
16619 use Composer\Util\Url as UrlUtil;
16620
16621
16622
16623
16624
16625
16626
16627
16628
16629 class FileDownloader implements DownloaderInterface, ChangeReportInterface
16630 {
16631 protected $io;
16632 protected $config;
16633 protected $rfs;
16634 protected $filesystem;
16635 protected $cache;
16636 protected $outputProgress = true;
16637 private $lastCacheWrites = array();
16638 private $eventDispatcher;
16639
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
16651 {
16652 $this->io = $io;
16653 $this->config = $config;
16654 $this->eventDispatcher = $eventDispatcher;
16655 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
16656 $this->filesystem = $filesystem ?: new Filesystem();
16657 $this->cache = $cache;
16658
16659 if ($this->cache && $this->cache->gcIsNecessary()) {
16660 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
16661 }
16662 }
16663
16664
16665
16666
16667 public function getInstallationSource()
16668 {
16669 return 'dist';
16670 }
16671
16672
16673
16674
16675 public function download(PackageInterface $package, $path, $output = true)
16676 {
16677 if (!$package->getDistUrl()) {
16678 throw new \InvalidArgumentException('The given package is missing url information');
16679 }
16680
16681 if ($output) {
16682 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
16683 }
16684
16685 $urls = $package->getDistUrls();
16686 while ($url = array_shift($urls)) {
16687 try {
16688 $fileName = $this->doDownload($package, $path, $url);
16689 break;
16690 } catch (\Exception $e) {
16691 if ($this->io->isDebug()) {
16692 $this->io->writeError('');
16693 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
16694 } elseif (count($urls)) {
16695 $this->io->writeError('');
16696 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
16697 }
16698
16699 if (!count($urls)) {
16700 throw $e;
16701 }
16702 }
16703 }
16704
16705 if ($output) {
16706 $this->io->writeError('');
16707 }
16708
16709 return $fileName;
16710 }
16711
16712 protected function doDownload(PackageInterface $package, $path, $url)
16713 {
16714 $this->filesystem->emptyDirectory($path);
16715
16716 $fileName = $this->getFileName($package, $path);
16717
16718 $processedUrl = $this->processUrl($package, $url);
16719 $origin = RemoteFilesystem::getOrigin($processedUrl);
16720
16721 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
16722 if ($this->eventDispatcher) {
16723 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
16724 }
16725 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
16726
16727 try {
16728 $checksum = $package->getDistSha1Checksum();
16729 $cacheKey = $this->getCacheKey($package, $processedUrl);
16730
16731
16732 if ($this->cache && (!$checksum || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) {
16733 $this->io->writeError('Loading from cache', false);
16734 } else {
16735
16736 if (!$this->outputProgress) {
16737 $this->io->writeError('Downloading', false);
16738 }
16739
16740
16741 $retries = 3;
16742 while ($retries--) {
16743 try {
16744 $rfs->copy($origin, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
16745 break;
16746 } catch (TransportException $e) {
16747
16748 if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
16749 throw $e;
16750 }
16751 $this->io->writeError('');
16752 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
16753 usleep(500000);
16754 }
16755 }
16756
16757 if (!$this->outputProgress) {
16758 $this->io->writeError(' (<comment>100%</comment>)', false);
16759 }
16760
16761 if ($this->cache) {
16762 $this->lastCacheWrites[$package->getName()] = $cacheKey;
16763 $this->cache->copyFrom($cacheKey, $fileName);
16764 }
16765 }
16766
16767 if (!file_exists($fileName)) {
16768 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
16769 .' directory is writable and you have internet connectivity');
16770 }
16771
16772 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
16773 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
16774 }
16775 } catch (\Exception $e) {
16776
16777 $this->filesystem->removeDirectory($path);
16778 $this->clearLastCacheWrite($package);
16779 throw $e;
16780 }
16781
16782 return $fileName;
16783 }
16784
16785
16786
16787
16788 public function setOutputProgress($outputProgress)
16789 {
16790 $this->outputProgress = $outputProgress;
16791
16792 return $this;
16793 }
16794
16795 protected function clearLastCacheWrite(PackageInterface $package)
16796 {
16797 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
16798 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
16799 unset($this->lastCacheWrites[$package->getName()]);
16800 }
16801 }
16802
16803
16804
16805
16806 public function update(PackageInterface $initial, PackageInterface $target, $path)
16807 {
16808 $name = $target->getName();
16809 $from = $initial->getFullPrettyVersion();
16810 $to = $target->getFullPrettyVersion();
16811
16812 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
16813 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
16814
16815 $this->remove($initial, $path, false);
16816 $this->download($target, $path, false);
16817
16818 $this->io->writeError('');
16819 }
16820
16821
16822
16823
16824 public function remove(PackageInterface $package, $path, $output = true)
16825 {
16826 if ($output) {
16827 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
16828 }
16829 if (!$this->filesystem->removeDirectory($path)) {
16830 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
16831 }
16832 }
16833
16834
16835
16836
16837
16838
16839
16840
16841 protected function getFileName(PackageInterface $package, $path)
16842 {
16843 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
16844 }
16845
16846
16847
16848
16849
16850
16851
16852
16853
16854 protected function processUrl(PackageInterface $package, $url)
16855 {
16856 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
16857 throw new \RuntimeException('You must enable the openssl extension to download files via https');
16858 }
16859
16860 if ($package->getDistReference()) {
16861 $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
16862 }
16863
16864 return $url;
16865 }
16866
16867 private function getCacheKey(PackageInterface $package, $processedUrl)
16868 {
16869
16870
16871
16872
16873 $cacheKey = sha1($processedUrl);
16874
16875 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
16876 }
16877
16878
16879
16880
16881
16882 public function getLocalChanges(PackageInterface $package, $targetDir)
16883 {
16884 $prevIO = $this->io;
16885 $prevProgress = $this->outputProgress;
16886
16887 $this->io = new NullIO;
16888 $this->io->loadConfiguration($this->config);
16889 $this->outputProgress = false;
16890 $e = null;
16891
16892 try {
16893 $this->download($package, $targetDir.'_compare', false);
16894
16895 $comparer = new Comparer();
16896 $comparer->setSource($targetDir.'_compare');
16897 $comparer->setUpdate($targetDir);
16898 $comparer->doCompare();
16899 $output = $comparer->getChanged(true, true);
16900 $this->filesystem->removeDirectory($targetDir.'_compare');
16901 } catch (\Exception $e) {
16902 }
16903
16904 $this->io = $prevIO;
16905 $this->outputProgress = $prevProgress;
16906
16907 if ($e) {
16908 throw $e;
16909 }
16910
16911 return trim($output);
16912 }
16913 }
16914 <?php
16915
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925
16926 namespace Composer\Downloader;
16927
16928
16929
16930
16931
16932
16933 class FilesystemException extends \Exception
16934 {
16935 public function __construct($message = '', $code = 0, \Exception $previous = null)
16936 {
16937 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
16938 }
16939 }
16940 <?php
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950
16951
16952 namespace Composer\Downloader;
16953
16954 use Composer\Package\PackageInterface;
16955 use Composer\Util\ProcessExecutor;
16956
16957
16958
16959
16960 class FossilDownloader extends VcsDownloader
16961 {
16962
16963
16964
16965 public function doDownload(PackageInterface $package, $path, $url)
16966 {
16967
16968 $this->config->prohibitUrlByConfig($url, $this->io);
16969
16970 $url = ProcessExecutor::escape($url);
16971 $ref = ProcessExecutor::escape($package->getSourceReference());
16972 $repoFile = $path . '.fossil';
16973 $this->io->writeError("Cloning ".$package->getSourceReference());
16974 $command = sprintf('fossil clone -- %s %s', $url, ProcessExecutor::escape($repoFile));
16975 if (0 !== $this->process->execute($command, $ignoredOutput)) {
16976 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16977 }
16978 $command = sprintf('fossil open --nested -- %s', ProcessExecutor::escape($repoFile));
16979 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16980 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16981 }
16982 $command = sprintf('fossil update -- %s', $ref);
16983 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16984 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16985 }
16986 }
16987
16988
16989
16990
16991 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16992 {
16993
16994 $this->config->prohibitUrlByConfig($url, $this->io);
16995
16996 $url = ProcessExecutor::escape($url);
16997 $ref = ProcessExecutor::escape($target->getSourceReference());
16998 $this->io->writeError(" Updating to ".$target->getSourceReference());
16999
17000 if (!$this->hasMetadataRepository($path)) {
17001 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
17002 }
17003
17004 $command = sprintf('fossil pull && fossil up %s', $ref);
17005 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
17006 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17007 }
17008 }
17009
17010
17011
17012
17013 public function getLocalChanges(PackageInterface $package, $path)
17014 {
17015 if (!$this->hasMetadataRepository($path)) {
17016 return null;
17017 }
17018
17019 $this->process->execute('fossil changes', $output, realpath($path));
17020
17021 return trim($output) ?: null;
17022 }
17023
17024
17025
17026
17027 protected function getCommitLogs($fromReference, $toReference, $path)
17028 {
17029 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', ProcessExecutor::escape($toReference));
17030
17031 if (0 !== $this->process->execute($command, $output, realpath($path))) {
17032 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17033 }
17034
17035 $log = '';
17036 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
17037
17038 foreach ($this->process->splitLines($output) as $line) {
17039 if (preg_match($match, $line)) {
17040 break;
17041 }
17042 $log .= $line;
17043 }
17044
17045 return $log;
17046 }
17047
17048
17049
17050
17051 protected function hasMetadataRepository($path)
17052 {
17053 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
17054 }
17055 }
17056 <?php
17057
17058
17059
17060
17061
17062
17063
17064
17065
17066
17067
17068 namespace Composer\Downloader;
17069
17070 use Composer\Config;
17071 use Composer\IO\IOInterface;
17072 use Composer\Package\PackageInterface;
17073 use Composer\Util\Filesystem;
17074 use Composer\Util\Git as GitUtil;
17075 use Composer\Util\Platform;
17076 use Composer\Util\ProcessExecutor;
17077 use Composer\Cache;
17078
17079
17080
17081
17082 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
17083 {
17084 private $hasStashedChanges = false;
17085 private $hasDiscardedChanges = false;
17086 private $gitUtil;
17087
17088 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
17089 {
17090 parent::__construct($io, $config, $process, $fs);
17091 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
17092 }
17093
17094
17095
17096
17097 public function doDownload(PackageInterface $package, $path, $url)
17098 {
17099 GitUtil::cleanEnv();
17100 $path = $this->normalizePath($path);
17101 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
17102 $ref = $package->getSourceReference();
17103 $flag = Platform::isWindows() ? '/D ' : '';
17104
17105
17106 $gitVersion = GitUtil::getVersion($this->process);
17107 $msg = "Cloning ".$this->getShortHash($ref);
17108
17109 $command = 'git clone --no-checkout -- %url% %path% && cd '.$flag.'%path% && git remote add composer -- %url% && git fetch composer && git remote set-url origin -- %sanitizedUrl% && git remote set-url composer -- %sanitizedUrl%';
17110 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
17111 $this->io->writeError('', true, IOInterface::DEBUG);
17112 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
17113 try {
17114 if (!$this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref)) {
17115 $this->io->writeError('<error>Failed to update '.$url.' in cache, package installation for '.$package->getPrettyName().' might fail.</error>');
17116 }
17117 if (is_dir($cachePath)) {
17118 $command =
17119 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
17120 . '&& cd '.$flag.'%path% '
17121 . '&& git remote set-url origin -- %sanitizedUrl% && git remote add composer -- %sanitizedUrl%';
17122 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
17123 }
17124 } catch (\RuntimeException $e) {
17125 if (0 === strpos(get_class($e), 'PHPUnit')) {
17126 throw $e;
17127 }
17128 }
17129 }
17130 $this->io->writeError($msg);
17131
17132 $commandCallable = function ($url) use ($path, $command, $cachePath) {
17133 return str_replace(
17134 array('%url%', '%path%', '%cachePath%', '%sanitizedUrl%'),
17135 array(
17136 ProcessExecutor::escape($url),
17137 ProcessExecutor::escape($path),
17138 ProcessExecutor::escape($cachePath),
17139 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url)),
17140 ),
17141 $command
17142 );
17143 };
17144
17145 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
17146 if ($url !== $package->getSourceUrl()) {
17147 $this->updateOriginUrl($path, $package->getSourceUrl());
17148 } else {
17149 $this->setPushUrl($path, $url);
17150 }
17151
17152 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
17153 if ($package->getDistReference() === $package->getSourceReference()) {
17154 $package->setDistReference($newRef);
17155 }
17156 $package->setSourceReference($newRef);
17157 }
17158 }
17159
17160
17161
17162
17163 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17164 {
17165 GitUtil::cleanEnv();
17166 if (!$this->hasMetadataRepository($path)) {
17167 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
17168 }
17169
17170 $updateOriginUrl = false;
17171 if (
17172 0 === $this->process->execute('git remote -v', $output, $path)
17173 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
17174 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
17175 ) {
17176 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
17177 $updateOriginUrl = true;
17178 }
17179 }
17180
17181 $ref = $target->getSourceReference();
17182 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
17183 $command = '(git remote set-url composer -- %s && git rev-parse --quiet --verify %s || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %s';
17184
17185 $commandCallable = function ($url) use ($command, $ref) {
17186 return sprintf(
17187 $command,
17188 ProcessExecutor::escape($url),
17189 ProcessExecutor::escape($ref.'^{commit}'),
17190 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url))
17191 );
17192 };
17193
17194 $this->gitUtil->runCommand($commandCallable, $url, $path);
17195 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
17196 if ($target->getDistReference() === $target->getSourceReference()) {
17197 $target->setDistReference($newRef);
17198 }
17199 $target->setSourceReference($newRef);
17200 }
17201
17202 if ($updateOriginUrl) {
17203 $this->updateOriginUrl($path, $target->getSourceUrl());
17204 }
17205 }
17206
17207
17208
17209
17210 public function getLocalChanges(PackageInterface $package, $path)
17211 {
17212 GitUtil::cleanEnv();
17213 if (!$this->hasMetadataRepository($path)) {
17214 return;
17215 }
17216
17217 $command = 'git status --porcelain --untracked-files=no';
17218 if (0 !== $this->process->execute($command, $output, $path)) {
17219 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17220 }
17221
17222 return trim($output) ?: null;
17223 }
17224
17225 public function getUnpushedChanges(PackageInterface $package, $path)
17226 {
17227 GitUtil::cleanEnv();
17228 $path = $this->normalizePath($path);
17229 if (!$this->hasMetadataRepository($path)) {
17230 return;
17231 }
17232
17233 $command = 'git show-ref --head -d';
17234 if (0 !== $this->process->execute($command, $output, $path)) {
17235 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17236 }
17237
17238 $refs = trim($output);
17239 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
17240
17241 return;
17242 }
17243
17244 $headRef = $match[1];
17245 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
17246
17247 return;
17248 }
17249
17250
17251 $branch = $matches[1][0];
17252 $unpushedChanges = null;
17253
17254
17255 for ($i = 0; $i <= 1; $i++) {
17256
17257 foreach ($matches[1] as $candidate) {
17258 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
17259 $branch = $candidate;
17260 $remoteBranch = $match[1];
17261 break;
17262 }
17263 }
17264
17265
17266
17267
17268 if (!isset($remoteBranch)) {
17269 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
17270 } else {
17271 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
17272 if (0 !== $this->process->execute($command, $output, $path)) {
17273 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17274 }
17275
17276 $unpushedChanges = trim($output) ?: null;
17277 }
17278
17279
17280
17281 if ($unpushedChanges && $i === 0) {
17282 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
17283 }
17284
17285
17286 if (!$unpushedChanges) {
17287 break;
17288 }
17289 }
17290
17291 return $unpushedChanges;
17292 }
17293
17294
17295
17296
17297 protected function cleanChanges(PackageInterface $package, $path, $update)
17298 {
17299 GitUtil::cleanEnv();
17300 $path = $this->normalizePath($path);
17301
17302 $unpushed = $this->getUnpushedChanges($package, $path);
17303 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
17304 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
17305 }
17306
17307 if (!$changes = $this->getLocalChanges($package, $path)) {
17308 return;
17309 }
17310
17311 if (!$this->io->isInteractive()) {
17312 $discardChanges = $this->config->get('discard-changes');
17313 if (true === $discardChanges) {
17314 return $this->discardChanges($path);
17315 }
17316 if ('stash' === $discardChanges) {
17317 if (!$update) {
17318 return parent::cleanChanges($package, $path, $update);
17319 }
17320
17321 return $this->stashChanges($path);
17322 }
17323
17324 return parent::cleanChanges($package, $path, $update);
17325 }
17326
17327 $changes = array_map(function ($elem) {
17328 return '    '.$elem;
17329 }, preg_split('{\s*\r?\n\s*}', $changes));
17330 $this->io->writeError('    <error>The package has modified files:</error>');
17331 $this->io->writeError(array_slice($changes, 0, 10));
17332 if (count($changes) > 10) {
17333 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
17334 }
17335
17336 while (true) {
17337 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
17338 case 'y':
17339 $this->discardChanges($path);
17340 break 2;
17341
17342 case 's':
17343 if (!$update) {
17344 goto help;
17345 }
17346
17347 $this->stashChanges($path);
17348 break 2;
17349
17350 case 'n':
17351 throw new \RuntimeException('Update aborted');
17352
17353 case 'v':
17354 $this->io->writeError($changes);
17355 break;
17356
17357 case 'd':
17358 $this->viewDiff($path);
17359 break;
17360
17361 case '?':
17362 default:
17363 help:
17364 $this->io->writeError(array(
17365 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
17366 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
17367 '    v - view modified files',
17368 '    d - view local modifications (diff)',
17369 ));
17370 if ($update) {
17371 $this->io->writeError('    s - stash changes and try to reapply them after the update');
17372 }
17373 $this->io->writeError('    ? - print help');
17374 break;
17375 }
17376 }
17377 }
17378
17379
17380
17381
17382 protected function reapplyChanges($path)
17383 {
17384 $path = $this->normalizePath($path);
17385 if ($this->hasStashedChanges) {
17386 $this->hasStashedChanges = false;
17387 $this->io->writeError('    <info>Re-applying stashed changes</info>');
17388 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
17389 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
17390 }
17391 }
17392
17393 $this->hasDiscardedChanges = false;
17394 }
17395
17396
17397
17398
17399
17400
17401
17402
17403
17404
17405
17406 protected function updateToCommit($path, $reference, $branch, $date)
17407 {
17408 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
17409
17410
17411
17412
17413
17414
17415 $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
17416 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
17417
17418 $branches = null;
17419 if (0 === $this->process->execute('git branch -r', $output, $path)) {
17420 $branches = $output;
17421 }
17422
17423
17424 $gitRef = $reference;
17425 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
17426 && $branches
17427 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
17428 ) {
17429 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
17430 if (0 === $this->process->execute($command, $output, $path)) {
17431 return;
17432 }
17433 }
17434
17435
17436 if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
17437
17438 if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
17439 $branch = 'v' . $branch;
17440 }
17441
17442 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
17443 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
17444 if (0 === $this->process->execute($command, $output, $path)
17445 || 0 === $this->process->execute($fallbackCommand, $output, $path)
17446 ) {
17447 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
17448 if (0 === $this->process->execute($command, $output, $path)) {
17449 return;
17450 }
17451 }
17452 }
17453
17454 $command = sprintf($template, ProcessExecutor::escape($gitRef));
17455 if (0 === $this->process->execute($command, $output, $path)) {
17456 return;
17457 }
17458
17459
17460 if (false !== strpos($this->process->getErrorOutput(), $reference)) {
17461 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
17462 }
17463
17464 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
17465 }
17466
17467 protected function updateOriginUrl($path, $url)
17468 {
17469 $this->process->execute(sprintf('git remote set-url origin -- %s', ProcessExecutor::escape($url)), $output, $path);
17470 $this->setPushUrl($path, $url);
17471 }
17472
17473 protected function setPushUrl($path, $url)
17474 {
17475
17476 if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
17477 $protocols = $this->config->get('github-protocols');
17478 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
17479 if (!in_array('ssh', $protocols, true)) {
17480 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
17481 }
17482 $cmd = sprintf('git remote set-url --push origin -- %s', ProcessExecutor::escape($pushUrl));
17483 $this->process->execute($cmd, $ignoredOutput, $path);
17484 }
17485 }
17486
17487
17488
17489
17490 protected function getCommitLogs($fromReference, $toReference, $path)
17491 {
17492 $path = $this->normalizePath($path);
17493 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"'.GitUtil::getNoShowSignatureFlag($this->process), ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
17494
17495 if (0 !== $this->process->execute($command, $output, $path)) {
17496 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17497 }
17498
17499 return $output;
17500 }
17501
17502
17503
17504
17505
17506 protected function discardChanges($path)
17507 {
17508 $path = $this->normalizePath($path);
17509 if (0 !== $this->process->execute('git clean -df && git reset --hard', $output, $path)) {
17510 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
17511 }
17512
17513 $this->hasDiscardedChanges = true;
17514 }
17515
17516
17517
17518
17519
17520 protected function stashChanges($path)
17521 {
17522 $path = $this->normalizePath($path);
17523 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
17524 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
17525 }
17526
17527 $this->hasStashedChanges = true;
17528 }
17529
17530
17531
17532
17533
17534 protected function viewDiff($path)
17535 {
17536 $path = $this->normalizePath($path);
17537 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
17538 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
17539 }
17540
17541 $this->io->writeError($output);
17542 }
17543
17544 protected function normalizePath($path)
17545 {
17546 if (Platform::isWindows() && strlen($path) > 0) {
17547 $basePath = $path;
17548 $removed = array();
17549
17550 while (!is_dir($basePath) && $basePath !== '\\') {
17551 array_unshift($removed, basename($basePath));
17552 $basePath = dirname($basePath);
17553 }
17554
17555 if ($basePath === '\\') {
17556 return $path;
17557 }
17558
17559 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
17560 }
17561
17562 return $path;
17563 }
17564
17565
17566
17567
17568 protected function hasMetadataRepository($path)
17569 {
17570 $path = $this->normalizePath($path);
17571
17572 return is_dir($path.'/.git');
17573 }
17574
17575 protected function getShortHash($reference)
17576 {
17577 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
17578 return substr($reference, 0, 10);
17579 }
17580
17581 return $reference;
17582 }
17583 }
17584 <?php
17585
17586
17587
17588
17589
17590
17591
17592
17593
17594
17595
17596 namespace Composer\Downloader;
17597
17598 use Composer\Config;
17599 use Composer\Cache;
17600 use Composer\EventDispatcher\EventDispatcher;
17601 use Composer\Package\PackageInterface;
17602 use Composer\Util\Platform;
17603 use Composer\Util\ProcessExecutor;
17604 use Composer\Util\RemoteFilesystem;
17605 use Composer\IO\IOInterface;
17606
17607
17608
17609
17610
17611
17612 class GzipDownloader extends ArchiveDownloader
17613 {
17614 protected $process;
17615
17616 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17617 {
17618 $this->process = $process ?: new ProcessExecutor($io);
17619 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17620 }
17621
17622 protected function extract($file, $path)
17623 {
17624 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
17625
17626
17627 if (!Platform::isWindows()) {
17628 $command = 'gzip -cd -- ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
17629
17630 if (0 === $this->process->execute($command, $ignoredOutput)) {
17631 return;
17632 }
17633
17634 if (extension_loaded('zlib')) {
17635
17636 $this->extractUsingExt($file, $targetFilepath);
17637
17638 return;
17639 }
17640
17641 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17642 throw new \RuntimeException($processError);
17643 }
17644
17645
17646 $this->extractUsingExt($file, $targetFilepath);
17647 }
17648
17649
17650
17651
17652 protected function getFileName(PackageInterface $package, $path)
17653 {
17654 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17655 }
17656
17657 private function extractUsingExt($file, $targetFilepath)
17658 {
17659 $archiveFile = gzopen($file, 'rb');
17660 $targetFile = fopen($targetFilepath, 'wb');
17661 while ($string = gzread($archiveFile, 4096)) {
17662 fwrite($targetFile, $string, Platform::strlen($string));
17663 }
17664 gzclose($archiveFile);
17665 fclose($targetFile);
17666 }
17667 }
17668 <?php
17669
17670
17671
17672
17673
17674
17675
17676
17677
17678
17679
17680 namespace Composer\Downloader;
17681
17682 use Composer\Package\PackageInterface;
17683 use Composer\Util\ProcessExecutor;
17684 use Composer\Util\Hg as HgUtils;
17685
17686
17687
17688
17689 class HgDownloader extends VcsDownloader
17690 {
17691
17692
17693
17694 public function doDownload(PackageInterface $package, $path, $url)
17695 {
17696 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
17697
17698 $cloneCommand = function ($url) use ($path) {
17699 return sprintf('hg clone -- %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
17700 };
17701
17702 $hgUtils->runCommand($cloneCommand, $url, $path);
17703
17704 $ref = ProcessExecutor::escape($package->getSourceReference());
17705 $command = sprintf('hg up -- %s', $ref);
17706 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
17707 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17708 }
17709 }
17710
17711
17712
17713
17714 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17715 {
17716 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
17717
17718 $ref = $target->getSourceReference();
17719 $this->io->writeError(" Updating to ".$target->getSourceReference());
17720
17721 if (!$this->hasMetadataRepository($path)) {
17722 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
17723 }
17724
17725 $command = function ($url) use ($ref) {
17726 return sprintf('hg pull -- %s && hg up -- %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
17727 };
17728
17729 $hgUtils->runCommand($command, $url, $path);
17730 }
17731
17732
17733
17734
17735 public function getLocalChanges(PackageInterface $package, $path)
17736 {
17737 if (!is_dir($path.'/.hg')) {
17738 return null;
17739 }
17740
17741 $this->process->execute('hg st', $output, realpath($path));
17742
17743 return trim($output) ?: null;
17744 }
17745
17746
17747
17748
17749 protected function getCommitLogs($fromReference, $toReference, $path)
17750 {
17751 $command = sprintf('hg log -r %s:%s --style compact', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
17752
17753 if (0 !== $this->process->execute($command, $output, realpath($path))) {
17754 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17755 }
17756
17757 return $output;
17758 }
17759
17760
17761
17762
17763 protected function hasMetadataRepository($path)
17764 {
17765 return is_dir($path . '/.hg');
17766 }
17767 }
17768 <?php
17769
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780 namespace Composer\Downloader;
17781
17782 use Composer\Package\Archiver\ArchivableFilesFinder;
17783 use Composer\Package\Dumper\ArrayDumper;
17784 use Composer\Package\PackageInterface;
17785 use Composer\Package\Version\VersionGuesser;
17786 use Composer\Package\Version\VersionParser;
17787 use Composer\Util\Platform;
17788 use Composer\Util\ProcessExecutor;
17789 use Composer\Util\Filesystem as ComposerFilesystem;
17790 use Symfony\Component\Filesystem\Exception\IOException;
17791 use Symfony\Component\Filesystem\Filesystem;
17792
17793
17794
17795
17796
17797
17798
17799 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
17800 {
17801 const STRATEGY_SYMLINK = 10;
17802 const STRATEGY_MIRROR = 20;
17803
17804
17805
17806
17807 public function download(PackageInterface $package, $path, $output = true)
17808 {
17809 $url = $package->getDistUrl();
17810 $realUrl = realpath($url);
17811 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
17812 throw new \RuntimeException(sprintf(
17813 'Source path "%s" is not found for package %s',
17814 $url,
17815 $package->getName()
17816 ));
17817 }
17818
17819 if (realpath($path) === $realUrl) {
17820 if ($output) {
17821 $this->io->writeError(sprintf(
17822 '  - Installing <info>%s</info> (<comment>%s</comment>): Source already present',
17823 $package->getName(),
17824 $package->getFullPrettyVersion()
17825 ));
17826 }
17827
17828 return;
17829 }
17830
17831 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
17832
17833
17834
17835
17836 throw new \RuntimeException(sprintf(
17837 'Package %s cannot install to "%s" inside its source at "%s"',
17838 $package->getName(),
17839 realpath($path),
17840 $realUrl
17841 ));
17842 }
17843
17844
17845 $transportOptions = $package->getTransportOptions() + array('symlink' => null, 'relative' => true);
17846
17847
17848 $currentStrategy = self::STRATEGY_SYMLINK;
17849 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
17850
17851 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
17852 if ($mirrorPathRepos) {
17853 $currentStrategy = self::STRATEGY_MIRROR;
17854 }
17855
17856 if (true === $transportOptions['symlink']) {
17857 $currentStrategy = self::STRATEGY_SYMLINK;
17858 $allowedStrategies = array(self::STRATEGY_SYMLINK);
17859 } elseif (false === $transportOptions['symlink']) {
17860 $currentStrategy = self::STRATEGY_MIRROR;
17861 $allowedStrategies = array(self::STRATEGY_MIRROR);
17862 }
17863
17864
17865 if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
17866 $currentStrategy = self::STRATEGY_MIRROR;
17867 $allowedStrategies = array(self::STRATEGY_MIRROR);
17868 }
17869
17870 $fileSystem = new Filesystem();
17871 $this->filesystem->removeDirectory($path);
17872
17873 if ($output) {
17874 $this->io->writeError(sprintf(
17875 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
17876 $package->getName(),
17877 $package->getFullPrettyVersion()
17878 ), false);
17879 }
17880
17881 $isFallback = false;
17882 if (self::STRATEGY_SYMLINK == $currentStrategy) {
17883 try {
17884 if (Platform::isWindows()) {
17885
17886 $this->io->writeError(sprintf('Junctioning from %s', $url), false);
17887 $this->filesystem->junction($realUrl, $path);
17888 } else {
17889 $absolutePath = $path;
17890 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
17891 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
17892 }
17893 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
17894 $path = rtrim($path, "/");
17895 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
17896 if ($transportOptions['relative']) {
17897 $fileSystem->symlink($shortestPath, $path);
17898 } else {
17899 $fileSystem->symlink($realUrl, $path);
17900 }
17901 }
17902 } catch (IOException $e) {
17903 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
17904 $this->io->writeError('');
17905 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
17906 $currentStrategy = self::STRATEGY_MIRROR;
17907 $isFallback = true;
17908 } else {
17909 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
17910 }
17911 }
17912 }
17913
17914
17915 if (self::STRATEGY_MIRROR == $currentStrategy) {
17916 $fs = new ComposerFilesystem();
17917 $realUrl = $fs->normalizePath($realUrl);
17918
17919 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
17920 $iterator = new ArchivableFilesFinder($realUrl, array());
17921 $fileSystem->mirror($realUrl, $path, $iterator);
17922 }
17923
17924 $this->io->writeError('');
17925 }
17926
17927
17928
17929
17930 public function remove(PackageInterface $package, $path, $output = true)
17931 {
17932 $realUrl = realpath($package->getDistUrl());
17933
17934 if (realpath($path) === $realUrl) {
17935 if ($output) {
17936 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>), source is still present in $path");
17937 }
17938
17939 return;
17940 }
17941
17942
17943
17944
17945
17946
17947 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
17948 if ($output) {
17949 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
17950 }
17951 if (!$this->filesystem->removeJunction($path)) {
17952 $this->io->writeError("    <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>");
17953 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
17954 }
17955 } else {
17956 parent::remove($package, $path, $output);
17957 }
17958 }
17959
17960
17961
17962
17963 public function getVcsReference(PackageInterface $package, $path)
17964 {
17965 $parser = new VersionParser;
17966 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
17967 $dumper = new ArrayDumper;
17968
17969 $packageConfig = $dumper->dump($package);
17970 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
17971 return $packageVersion['commit'];
17972 }
17973 }
17974
17975
17976
17977
17978
17979
17980
17981
17982
17983
17984
17985
17986
17987
17988 private function safeJunctions()
17989 {
17990
17991 return function_exists('proc_open') &&
17992 (PHP_WINDOWS_VERSION_MAJOR > 6 ||
17993 (PHP_WINDOWS_VERSION_MAJOR === 6 && PHP_WINDOWS_VERSION_MINOR >= 1));
17994 }
17995 }
17996 <?php
17997
17998
17999
18000
18001
18002
18003
18004
18005
18006
18007
18008 namespace Composer\Downloader;
18009
18010 use Composer\Util\Filesystem;
18011
18012
18013
18014
18015
18016
18017
18018
18019
18020
18021 class PearPackageExtractor
18022 {
18023 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
18024
18025 private $filesystem;
18026 private $file;
18027
18028 public function __construct($file)
18029 {
18030 if (!is_file($file)) {
18031 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
18032 }
18033
18034 $this->filesystem = new Filesystem();
18035 $this->file = $file;
18036 }
18037
18038
18039
18040
18041
18042
18043
18044
18045
18046
18047 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
18048 {
18049 $extractionPath = $target.'/tarball';
18050
18051 try {
18052 $archive = new \PharData($this->file);
18053 $archive->extractTo($extractionPath, null, true);
18054
18055 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
18056 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
18057 }
18058
18059 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
18060 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
18061 $this->filesystem->removeDirectory($extractionPath);
18062 } catch (\Exception $exception) {
18063 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
18064 }
18065 }
18066
18067
18068
18069
18070
18071
18072
18073
18074
18075
18076 private function copyFiles($files, $source, $target, $roles, $vars)
18077 {
18078 foreach ($files as $file) {
18079 $from = $this->combine($source, $file['from']);
18080 $to = $this->combine($target, $roles[$file['role']]);
18081 $to = $this->combine($to, $file['to']);
18082 $tasks = $file['tasks'];
18083 $this->copyFile($from, $to, $tasks, $vars);
18084 }
18085 }
18086
18087 private function copyFile($from, $to, $tasks, $vars)
18088 {
18089 if (!is_file($from)) {
18090 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
18091 }
18092
18093 $this->filesystem->ensureDirectoryExists(dirname($to));
18094
18095 if (0 == count($tasks)) {
18096 $copied = copy($from, $to);
18097 } else {
18098 $content = file_get_contents($from);
18099 $replacements = array();
18100 foreach ($tasks as $task) {
18101 $pattern = $task['from'];
18102 $varName = $task['to'];
18103 if (isset($vars[$varName])) {
18104 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
18105 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
18106 } else {
18107 $replacements[$pattern] = $vars[$varName];
18108 }
18109 }
18110 }
18111 $content = strtr($content, $replacements);
18112
18113 $copied = file_put_contents($to, $content);
18114 }
18115
18116 if (false === $copied) {
18117 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
18118 }
18119 }
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130
18131 private function buildCopyActions($source, array $roles, $vars)
18132 {
18133
18134 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
18135 if (false === $package) {
18136 throw new \RuntimeException('Package definition file is not valid.');
18137 }
18138
18139 $packageSchemaVersion = $package['version'];
18140 if ('1.0' == $packageSchemaVersion) {
18141 $children = $package->release->filelist->children();
18142 $packageName = (string) $package->name;
18143 $packageVersion = (string) $package->release->version;
18144 $sourceDir = $packageName . '-' . $packageVersion;
18145 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
18146 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
18147 $children = $package->contents->children();
18148 $packageName = (string) $package->name;
18149 $packageVersion = (string) $package->version->release;
18150 $sourceDir = $packageName . '-' . $packageVersion;
18151 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
18152
18153 $namespaces = $package->getNamespaces();
18154 $package->registerXPathNamespace('ns', $namespaces['']);
18155 $releaseNodes = $package->xpath('ns:phprelease');
18156 $this->applyRelease($result, $releaseNodes, $vars);
18157 } else {
18158 throw new \RuntimeException('Unsupported schema version of package definition file.');
18159 }
18160
18161 return $result;
18162 }
18163
18164 private function applyRelease(&$actions, $releaseNodes, $vars)
18165 {
18166 foreach ($releaseNodes as $releaseNode) {
18167 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
18168 if ($requiredOs && $vars['os'] != $requiredOs) {
18169 continue;
18170 }
18171
18172 if ($releaseNode->filelist) {
18173 foreach ($releaseNode->filelist->children() as $action) {
18174 if ('install' == $action->getName()) {
18175 $name = (string) $action['name'];
18176 $as = (string) $action['as'];
18177 if (isset($actions[$name])) {
18178 $actions[$name]['to'] = $as;
18179 }
18180 } elseif ('ignore' == $action->getName()) {
18181 $name = (string) $action['name'];
18182 unset($actions[$name]);
18183 } else {
18184
18185 }
18186 }
18187 }
18188 break;
18189 }
18190 }
18191
18192 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
18193 {
18194 $result = array();
18195
18196
18197 foreach ($children as $child) {
18198
18199 if ($child->getName() == 'dir') {
18200 $dirSource = $this->combine($source, (string) $child['name']);
18201 $dirTarget = $child['baseinstalldir'] ?: $target;
18202 $dirRole = $child['role'] ?: $role;
18203 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
18204 $result = array_merge($result, $dirFiles);
18205 } elseif ($child->getName() == 'file') {
18206 $fileRole = (string) $child['role'] ?: $role;
18207 if (isset($targetRoles[$fileRole])) {
18208 $fileName = (string) ($child['name'] ?: $child[0]); 
18209 $fileSource = $this->combine($source, $fileName);
18210 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
18211 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
18212 $fileTarget = $packageName . '/' . $fileTarget;
18213 }
18214 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
18215 }
18216 }
18217 }
18218
18219 return $result;
18220 }
18221
18222 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
18223 {
18224 $result = array();
18225
18226
18227 foreach ($children as $child) {
18228
18229 if ('dir' == $child->getName()) {
18230 $dirSource = $this->combine($source, $child['name']);
18231 $dirTarget = $child['baseinstalldir'] ?: $target;
18232 $dirRole = $child['role'] ?: $role;
18233 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
18234 $result = array_merge($result, $dirFiles);
18235 } elseif ('file' == $child->getName()) {
18236 $fileRole = (string) $child['role'] ?: $role;
18237 if (isset($targetRoles[$fileRole])) {
18238 $fileSource = $this->combine($source, (string) $child['name']);
18239 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
18240 $fileTasks = array();
18241 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
18242 if ('replace' == $taskNode->getName()) {
18243 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
18244 }
18245 }
18246 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
18247 $fileTarget = $packageName . '/' . $fileTarget;
18248 }
18249 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
18250 }
18251 }
18252 }
18253
18254 return $result;
18255 }
18256
18257 private function combine($left, $right)
18258 {
18259 return rtrim($left, '/') . '/' . ltrim($right, '/');
18260 }
18261 }
18262 <?php
18263
18264
18265
18266
18267
18268
18269
18270
18271
18272
18273
18274 namespace Composer\Downloader;
18275
18276 use Composer\Package\PackageInterface;
18277 use Composer\Repository\VcsRepository;
18278 use Composer\Util\Perforce;
18279
18280
18281
18282
18283 class PerforceDownloader extends VcsDownloader
18284 {
18285
18286 protected $perforce;
18287
18288
18289
18290
18291 public function doDownload(PackageInterface $package, $path, $url)
18292 {
18293 $ref = $package->getSourceReference();
18294 $label = $this->getLabelFromSourceReference($ref);
18295
18296 $this->io->writeError('Cloning ' . $ref);
18297 $this->initPerforce($package, $path, $url);
18298 $this->perforce->setStream($ref);
18299 $this->perforce->p4Login();
18300 $this->perforce->writeP4ClientSpec();
18301 $this->perforce->connectClient();
18302 $this->perforce->syncCodeBase($label);
18303 $this->perforce->cleanupClientSpec();
18304 }
18305
18306 private function getLabelFromSourceReference($ref)
18307 {
18308 $pos = strpos($ref, '@');
18309 if (false !== $pos) {
18310 return substr($ref, $pos + 1);
18311 }
18312
18313 return null;
18314 }
18315
18316 public function initPerforce(PackageInterface $package, $path, $url)
18317 {
18318 if (!empty($this->perforce)) {
18319 $this->perforce->initializePath($path);
18320
18321 return;
18322 }
18323
18324 $repository = $package->getRepository();
18325 $repoConfig = null;
18326 if ($repository instanceof VcsRepository) {
18327 $repoConfig = $this->getRepoConfig($repository);
18328 }
18329 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
18330 }
18331
18332 private function getRepoConfig(VcsRepository $repository)
18333 {
18334 return $repository->getRepoConfig();
18335 }
18336
18337
18338
18339
18340 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
18341 {
18342 $this->doDownload($target, $path, $url);
18343 }
18344
18345
18346
18347
18348 public function getLocalChanges(PackageInterface $package, $path)
18349 {
18350 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
18351 }
18352
18353
18354
18355
18356 protected function getCommitLogs($fromReference, $toReference, $path)
18357 {
18358 return $this->perforce->getCommitLogs($fromReference, $toReference);
18359 }
18360
18361 public function setPerforce($perforce)
18362 {
18363 $this->perforce = $perforce;
18364 }
18365
18366
18367
18368
18369 protected function hasMetadataRepository($path)
18370 {
18371 return true;
18372 }
18373 }
18374 <?php
18375
18376
18377
18378
18379
18380
18381
18382
18383
18384
18385
18386 namespace Composer\Downloader;
18387
18388
18389
18390
18391
18392
18393 class PharDownloader extends ArchiveDownloader
18394 {
18395
18396
18397
18398 protected function extract($file, $path)
18399 {
18400
18401 $archive = new \Phar($file);
18402 $archive->extractTo($path, null, true);
18403
18404
18405
18406
18407
18408 }
18409 }
18410 <?php
18411
18412
18413
18414
18415
18416
18417
18418
18419
18420
18421
18422 namespace Composer\Downloader;
18423
18424 use Composer\Config;
18425 use Composer\Cache;
18426 use Composer\EventDispatcher\EventDispatcher;
18427 use Composer\Util\IniHelper;
18428 use Composer\Util\Platform;
18429 use Composer\Util\ProcessExecutor;
18430 use Composer\Util\RemoteFilesystem;
18431 use Composer\IO\IOInterface;
18432 use RarArchive;
18433
18434
18435
18436
18437
18438
18439
18440
18441 class RarDownloader extends ArchiveDownloader
18442 {
18443 protected $process;
18444
18445 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18446 {
18447 $this->process = $process ?: new ProcessExecutor($io);
18448 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
18449 }
18450
18451 protected function extract($file, $path)
18452 {
18453 $processError = null;
18454
18455
18456 if (!Platform::isWindows()) {
18457 $command = 'unrar x -- ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
18458
18459 if (0 === $this->process->execute($command, $ignoredOutput)) {
18460 return;
18461 }
18462
18463 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
18464 }
18465
18466 if (!class_exists('RarArchive')) {
18467
18468 $iniMessage = IniHelper::getMessage();
18469
18470 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
18471 . $iniMessage . "\n" . $processError;
18472
18473 if (!Platform::isWindows()) {
18474 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
18475 }
18476
18477 throw new \RuntimeException($error);
18478 }
18479
18480 $rarArchive = RarArchive::open($file);
18481
18482 if (false === $rarArchive) {
18483 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
18484 }
18485
18486 $entries = $rarArchive->getEntries();
18487
18488 if (false === $entries) {
18489 throw new \RuntimeException('Could not retrieve RAR archive entries');
18490 }
18491
18492 foreach ($entries as $entry) {
18493 if (false === $entry->extract($path)) {
18494 throw new \RuntimeException('Could not extract entry');
18495 }
18496 }
18497
18498 $rarArchive->close();
18499 }
18500 }
18501 <?php
18502
18503
18504
18505
18506
18507
18508
18509
18510
18511
18512
18513 namespace Composer\Downloader;
18514
18515 use Composer\Package\PackageInterface;
18516 use Composer\Util\Svn as SvnUtil;
18517 use Composer\Repository\VcsRepository;
18518 use Composer\Util\ProcessExecutor;
18519
18520
18521
18522
18523
18524 class SvnDownloader extends VcsDownloader
18525 {
18526 protected $cacheCredentials = true;
18527
18528
18529
18530
18531 public function doDownload(PackageInterface $package, $path, $url)
18532 {
18533 SvnUtil::cleanEnv();
18534 $ref = $package->getSourceReference();
18535
18536 $repo = $package->getRepository();
18537 if ($repo instanceof VcsRepository) {
18538 $repoConfig = $repo->getRepoConfig();
18539 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
18540 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
18541 }
18542 }
18543
18544 $this->io->writeError(" Checking out ".$package->getSourceReference());
18545 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
18546 }
18547
18548
18549
18550
18551 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
18552 {
18553 SvnUtil::cleanEnv();
18554 $ref = $target->getSourceReference();
18555
18556 if (!$this->hasMetadataRepository($path)) {
18557 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
18558 }
18559
18560 $util = new SvnUtil($url, $this->io, $this->config);
18561 $flags = "";
18562 if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
18563 $flags .= ' --ignore-ancestry';
18564 }
18565
18566 $this->io->writeError(" Checking out " . $ref);
18567 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
18568 }
18569
18570
18571
18572
18573 public function getLocalChanges(PackageInterface $package, $path)
18574 {
18575 if (!$this->hasMetadataRepository($path)) {
18576 return null;
18577 }
18578
18579 $this->process->execute('svn status --ignore-externals', $output, $path);
18580
18581 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
18582 }
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
18597 {
18598 $util = new SvnUtil($baseUrl, $this->io, $this->config);
18599 $util->setCacheCredentials($this->cacheCredentials);
18600 try {
18601 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
18602 } catch (\RuntimeException $e) {
18603 throw new \RuntimeException(
18604 'Package could not be downloaded, '.$e->getMessage()
18605 );
18606 }
18607 }
18608
18609
18610
18611
18612 protected function cleanChanges(PackageInterface $package, $path, $update)
18613 {
18614 if (!$changes = $this->getLocalChanges($package, $path)) {
18615 return;
18616 }
18617
18618 if (!$this->io->isInteractive()) {
18619 if (true === $this->config->get('discard-changes')) {
18620 return $this->discardChanges($path);
18621 }
18622
18623 return parent::cleanChanges($package, $path, $update);
18624 }
18625
18626 $changes = array_map(function ($elem) {
18627 return '    '.$elem;
18628 }, preg_split('{\s*\r?\n\s*}', $changes));
18629 $countChanges = count($changes);
18630 $this->io->writeError(sprintf('    <error>The package has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
18631 $this->io->writeError(array_slice($changes, 0, 10));
18632 if ($countChanges > 10) {
18633 $remainingChanges = $countChanges - 10;
18634 $this->io->writeError(
18635 sprintf(
18636 '    <info>'.$remainingChanges.' more file%s modified, choose "v" to view the full list</info>',
18637 $remainingChanges === 1 ? '' : 's'
18638 )
18639 );
18640 }
18641
18642 while (true) {
18643 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
18644 case 'y':
18645 $this->discardChanges($path);
18646 break 2;
18647
18648 case 'n':
18649 throw new \RuntimeException('Update aborted');
18650
18651 case 'v':
18652 $this->io->writeError($changes);
18653 break;
18654
18655 case '?':
18656 default:
18657 $this->io->writeError(array(
18658 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
18659 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
18660 '    v - view modified files',
18661 '    ? - print help',
18662 ));
18663 break;
18664 }
18665 }
18666 }
18667
18668
18669
18670
18671 protected function getCommitLogs($fromReference, $toReference, $path)
18672 {
18673 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
18674
18675 $command = sprintf('svn info --non-interactive --xml -- %s', ProcessExecutor::escape($path));
18676 if (0 !== $this->process->execute($command, $output, $path)) {
18677 throw new \RuntimeException(
18678 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
18679 );
18680 }
18681
18682 $urlPattern = '#<url>(.*)</url>#';
18683 if (preg_match($urlPattern, $output, $matches)) {
18684 $baseUrl = $matches[1];
18685 } else {
18686 throw new \RuntimeException(
18687 'Unable to determine svn url for path '. $path
18688 );
18689 }
18690
18691
18692 $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
18693 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
18694
18695 $command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision));
18696
18697 $util = new SvnUtil($baseUrl, $this->io, $this->config);
18698 $util->setCacheCredentials($this->cacheCredentials);
18699 try {
18700 return $util->executeLocal($command, $path, null, $this->io->isVerbose());
18701 } catch (\RuntimeException $e) {
18702 throw new \RuntimeException(
18703 'Failed to execute ' . $command . "\n\n".$e->getMessage()
18704 );
18705 }
18706 }
18707
18708 return "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
18709 }
18710
18711 protected function discardChanges($path)
18712 {
18713 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
18714 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
18715 }
18716 }
18717
18718
18719
18720
18721 protected function hasMetadataRepository($path)
18722 {
18723 return is_dir($path.'/.svn');
18724 }
18725 }
18726 <?php
18727
18728
18729
18730
18731
18732
18733
18734
18735
18736
18737
18738 namespace Composer\Downloader;
18739
18740
18741
18742
18743
18744
18745 class TarDownloader extends ArchiveDownloader
18746 {
18747
18748
18749
18750 protected function extract($file, $path)
18751 {
18752
18753 $archive = new \PharData($file);
18754 $archive->extractTo($path, null, true);
18755 }
18756 }
18757 <?php
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768
18769 namespace Composer\Downloader;
18770
18771
18772
18773
18774 class TransportException extends \RuntimeException
18775 {
18776 protected $headers;
18777 protected $response;
18778 protected $statusCode;
18779
18780 public function setHeaders($headers)
18781 {
18782 $this->headers = $headers;
18783 }
18784
18785 public function getHeaders()
18786 {
18787 return $this->headers;
18788 }
18789
18790 public function setResponse($response)
18791 {
18792 $this->response = $response;
18793 }
18794
18795 public function getResponse()
18796 {
18797 return $this->response;
18798 }
18799
18800 public function setStatusCode($statusCode)
18801 {
18802 $this->statusCode = $statusCode;
18803 }
18804
18805 public function getStatusCode()
18806 {
18807 return $this->statusCode;
18808 }
18809 }
18810 <?php
18811
18812
18813
18814
18815
18816
18817
18818
18819
18820
18821
18822 namespace Composer\Downloader;
18823
18824 use Composer\Package\PackageInterface;
18825
18826
18827
18828
18829
18830
18831 interface VcsCapableDownloaderInterface
18832 {
18833
18834
18835
18836
18837
18838
18839
18840 public function getVcsReference(PackageInterface $package, $path);
18841 }
18842 <?php
18843
18844
18845
18846
18847
18848
18849
18850
18851
18852
18853
18854 namespace Composer\Downloader;
18855
18856 use Composer\Config;
18857 use Composer\Package\Dumper\ArrayDumper;
18858 use Composer\Package\PackageInterface;
18859 use Composer\Package\Version\VersionGuesser;
18860 use Composer\Package\Version\VersionParser;
18861 use Composer\Util\ProcessExecutor;
18862 use Composer\IO\IOInterface;
18863 use Composer\Util\Filesystem;
18864
18865
18866
18867
18868 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
18869 {
18870
18871 protected $io;
18872
18873 protected $config;
18874
18875 protected $process;
18876
18877 protected $filesystem;
18878
18879 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
18880 {
18881 $this->io = $io;
18882 $this->config = $config;
18883 $this->process = $process ?: new ProcessExecutor($io);
18884 $this->filesystem = $fs ?: new Filesystem($this->process);
18885 }
18886
18887
18888
18889
18890 public function getInstallationSource()
18891 {
18892 return 'source';
18893 }
18894
18895
18896
18897
18898 public function download(PackageInterface $package, $path)
18899 {
18900 if (!$package->getSourceReference()) {
18901 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
18902 }
18903
18904 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
18905 $this->filesystem->emptyDirectory($path);
18906
18907 $urls = $package->getSourceUrls();
18908 while ($url = array_shift($urls)) {
18909 try {
18910 if (Filesystem::isLocalPath($url)) {
18911
18912
18913 $needle = 'file://';
18914 $isFileProtocol = false;
18915 if (0 === strpos($url, $needle)) {
18916 $url = substr($url, strlen($needle));
18917 $isFileProtocol = true;
18918 }
18919
18920
18921 if (false !== strpos($url, '%')) {
18922 $url = rawurldecode($url);
18923 }
18924
18925 $url = realpath($url);
18926
18927 if ($isFileProtocol) {
18928 $url = $needle . $url;
18929 }
18930 }
18931 $this->doDownload($package, $path, $url);
18932 break;
18933 } catch (\Exception $e) {
18934
18935 if ($e instanceof \PHPUnit_Framework_Exception) {
18936 throw $e;
18937 }
18938 if ($this->io->isDebug()) {
18939 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
18940 } elseif (count($urls)) {
18941 $this->io->writeError('    Failed, trying the next URL');
18942 }
18943 if (!count($urls)) {
18944 throw $e;
18945 }
18946 }
18947 }
18948 }
18949
18950
18951
18952
18953 public function update(PackageInterface $initial, PackageInterface $target, $path)
18954 {
18955 if (!$target->getSourceReference()) {
18956 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
18957 }
18958
18959 $name = $target->getName();
18960 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
18961 if ($target->getSourceType() === 'svn') {
18962 $from = $initial->getSourceReference();
18963 $to = $target->getSourceReference();
18964 } else {
18965 $from = substr($initial->getSourceReference(), 0, 7);
18966 $to = substr($target->getSourceReference(), 0, 7);
18967 }
18968 $name .= ' '.$initial->getPrettyVersion();
18969 } else {
18970 $from = $initial->getFullPrettyVersion();
18971 $to = $target->getFullPrettyVersion();
18972 }
18973
18974 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
18975 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
18976
18977 $this->cleanChanges($initial, $path, true);
18978 $urls = $target->getSourceUrls();
18979
18980 $exception = null;
18981 while ($url = array_shift($urls)) {
18982 try {
18983 if (Filesystem::isLocalPath($url)) {
18984 $url = realpath($url);
18985 }
18986 $this->doUpdate($initial, $target, $path, $url);
18987
18988 $exception = null;
18989 break;
18990 } catch (\Exception $exception) {
18991
18992 if ($exception instanceof \PHPUnit_Framework_Exception) {
18993 throw $exception;
18994 }
18995 if ($this->io->isDebug()) {
18996 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
18997 } elseif (count($urls)) {
18998 $this->io->writeError('    Failed, trying the next URL');
18999 }
19000 }
19001 }
19002
19003 $this->reapplyChanges($path);
19004
19005
19006
19007 if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
19008 $message = 'Pulling in changes:';
19009 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
19010
19011 if (!trim($logs)) {
19012 $message = 'Rolling back changes:';
19013 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
19014 }
19015
19016 if (trim($logs)) {
19017 $logs = implode("\n", array_map(function ($line) {
19018 return '      ' . $line;
19019 }, explode("\n", $logs)));
19020
19021
19022 $logs = str_replace('<', '\<', $logs);
19023
19024 $this->io->writeError('    '.$message);
19025 $this->io->writeError($logs);
19026 }
19027 }
19028
19029 if (!$urls && $exception) {
19030 throw $exception;
19031 }
19032 }
19033
19034
19035
19036
19037 public function remove(PackageInterface $package, $path)
19038 {
19039 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
19040 $this->cleanChanges($package, $path, false);
19041 if (!$this->filesystem->removeDirectory($path)) {
19042 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
19043 }
19044 }
19045
19046
19047
19048
19049
19050 public function setOutputProgress($outputProgress)
19051 {
19052 return $this;
19053 }
19054
19055
19056
19057
19058 public function getVcsReference(PackageInterface $package, $path)
19059 {
19060 $parser = new VersionParser;
19061 $guesser = new VersionGuesser($this->config, $this->process, $parser);
19062 $dumper = new ArrayDumper;
19063
19064 $packageConfig = $dumper->dump($package);
19065 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
19066 return $packageVersion['commit'];
19067 }
19068 }
19069
19070
19071
19072
19073
19074
19075
19076
19077
19078
19079 protected function cleanChanges(PackageInterface $package, $path, $update)
19080 {
19081
19082 if (null !== $this->getLocalChanges($package, $path)) {
19083 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
19084 }
19085 }
19086
19087
19088
19089
19090
19091
19092
19093 protected function reapplyChanges($path)
19094 {
19095 }
19096
19097
19098
19099
19100
19101
19102
19103
19104 abstract protected function doDownload(PackageInterface $package, $path, $url);
19105
19106
19107
19108
19109
19110
19111
19112
19113
19114 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
19115
19116
19117
19118
19119
19120
19121
19122
19123
19124 abstract protected function getCommitLogs($fromReference, $toReference, $path);
19125
19126
19127
19128
19129
19130
19131
19132
19133 abstract protected function hasMetadataRepository($path);
19134 }
19135 <?php
19136
19137
19138
19139
19140
19141
19142
19143
19144
19145
19146
19147 namespace Composer\Downloader;
19148
19149 use Composer\Config;
19150 use Composer\Cache;
19151 use Composer\EventDispatcher\EventDispatcher;
19152 use Composer\Package\PackageInterface;
19153 use Composer\Util\ProcessExecutor;
19154 use Composer\Util\RemoteFilesystem;
19155 use Composer\IO\IOInterface;
19156
19157
19158
19159
19160
19161
19162
19163 class XzDownloader extends ArchiveDownloader
19164 {
19165 protected $process;
19166
19167 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
19168 {
19169 $this->process = $process ?: new ProcessExecutor($io);
19170
19171 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
19172 }
19173
19174 protected function extract($file, $path)
19175 {
19176 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
19177
19178 if (0 === $this->process->execute($command, $ignoredOutput)) {
19179 return;
19180 }
19181
19182 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
19183
19184 throw new \RuntimeException($processError);
19185 }
19186
19187
19188
19189
19190 protected function getFileName(PackageInterface $package, $path)
19191 {
19192 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
19193 }
19194 }
19195 <?php
19196
19197
19198
19199
19200
19201
19202
19203
19204
19205
19206
19207 namespace Composer\Downloader;
19208
19209 use Composer\Config;
19210 use Composer\Cache;
19211 use Composer\EventDispatcher\EventDispatcher;
19212 use Composer\Package\PackageInterface;
19213 use Composer\Util\IniHelper;
19214 use Composer\Util\Platform;
19215 use Composer\Util\ProcessExecutor;
19216 use Composer\Util\RemoteFilesystem;
19217 use Composer\IO\IOInterface;
19218 use Symfony\Component\Process\ExecutableFinder;
19219 use ZipArchive;
19220
19221
19222
19223
19224 class ZipDownloader extends ArchiveDownloader
19225 {
19226 protected static $hasSystemUnzip;
19227 private static $hasZipArchive;
19228 private static $isWindows;
19229
19230 protected $process;
19231 private $zipArchiveObject;
19232
19233 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
19234 {
19235 $this->process = $process ?: new ProcessExecutor($io);
19236 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
19237 }
19238
19239
19240
19241
19242 public function download(PackageInterface $package, $path, $output = true)
19243 {
19244 if (null === self::$hasSystemUnzip) {
19245 $finder = new ExecutableFinder;
19246 self::$hasSystemUnzip = (bool) $finder->find('unzip');
19247 }
19248
19249 if (null === self::$hasZipArchive) {
19250 self::$hasZipArchive = class_exists('ZipArchive');
19251 }
19252
19253 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
19254
19255 $iniMessage = IniHelper::getMessage();
19256 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
19257
19258 throw new \RuntimeException($error);
19259 }
19260
19261 if (null === self::$isWindows) {
19262 self::$isWindows = Platform::isWindows();
19263
19264 if (!self::$isWindows && !self::$hasSystemUnzip) {
19265 $this->io->writeError("<warning>As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.</warning>");
19266 $this->io->writeError("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>");
19267 $this->io->writeError("<warning>Installing 'unzip' may remediate them.</warning>");
19268 }
19269 }
19270
19271 return parent::download($package, $path, $output);
19272 }
19273
19274
19275
19276
19277
19278
19279
19280
19281
19282 protected function extractWithSystemUnzip($file, $path, $isLastChance)
19283 {
19284 if (!self::$hasZipArchive) {
19285
19286 $isLastChance = true;
19287 }
19288
19289 if (!self::$hasSystemUnzip && !$isLastChance) {
19290
19291
19292 return $this->extractWithZipArchive($file, $path, true);
19293 }
19294
19295 $processError = null;
19296
19297 $overwrite = $isLastChance ? '-o' : '';
19298
19299 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
19300
19301 try {
19302 if (0 === $exitCode = $this->process->execute($command, $ignoredOutput)) {
19303 return true;
19304 }
19305
19306 $processError = new \RuntimeException('Failed to execute ('.$exitCode.') '.$command."\n\n".$this->process->getErrorOutput());
19307 } catch (\Exception $e) {
19308 $processError = $e;
19309 }
19310
19311 if ($isLastChance) {
19312 throw $processError;
19313 }
19314
19315 $this->io->writeError('    '.$processError->getMessage());
19316 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
19317 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
19318
19319 return $this->extractWithZipArchive($file, $path, true);
19320 }
19321
19322
19323
19324
19325
19326
19327
19328
19329
19330 protected function extractWithZipArchive($file, $path, $isLastChance)
19331 {
19332 if (!self::$hasSystemUnzip) {
19333
19334 $isLastChance = true;
19335 }
19336
19337 if (!self::$hasZipArchive && !$isLastChance) {
19338
19339
19340 return $this->extractWithSystemUnzip($file, $path, true);
19341 }
19342
19343 $processError = null;
19344 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
19345
19346 try {
19347 if (true === ($retval = $zipArchive->open($file))) {
19348 $extractResult = $zipArchive->extractTo($path);
19349
19350 if (true === $extractResult) {
19351 $zipArchive->close();
19352
19353 return true;
19354 }
19355
19356 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
19357 } else {
19358 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
19359 }
19360 } catch (\ErrorException $e) {
19361 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
19362 } catch (\Exception $e) {
19363 $processError = $e;
19364 }
19365
19366 if ($isLastChance) {
19367 throw $processError;
19368 }
19369
19370 $this->io->writeError('    '.$processError->getMessage());
19371 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
19372
19373 return $this->extractWithSystemUnzip($file, $path, true);
19374 }
19375
19376
19377
19378
19379
19380
19381
19382 public function extract($file, $path)
19383 {
19384
19385 if (self::$isWindows) {
19386 $this->extractWithZipArchive($file, $path, false);
19387 } else {
19388 $this->extractWithSystemUnzip($file, $path, false);
19389 }
19390 }
19391
19392
19393
19394
19395
19396
19397
19398
19399 protected function getErrorMessage($retval, $file)
19400 {
19401 switch ($retval) {
19402 case ZipArchive::ER_EXISTS:
19403 return sprintf("File '%s' already exists.", $file);
19404 case ZipArchive::ER_INCONS:
19405 return sprintf("Zip archive '%s' is inconsistent.", $file);
19406 case ZipArchive::ER_INVAL:
19407 return sprintf("Invalid argument (%s)", $file);
19408 case ZipArchive::ER_MEMORY:
19409 return sprintf("Malloc failure (%s)", $file);
19410 case ZipArchive::ER_NOENT:
19411 return sprintf("No such zip file: '%s'", $file);
19412 case ZipArchive::ER_NOZIP:
19413 return sprintf("'%s' is not a zip archive.", $file);
19414 case ZipArchive::ER_OPEN:
19415 return sprintf("Can't open zip file: %s", $file);
19416 case ZipArchive::ER_READ:
19417 return sprintf("Zip read error (%s)", $file);
19418 case ZipArchive::ER_SEEK:
19419 return sprintf("Zip seek error (%s)", $file);
19420 default:
19421 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
19422 }
19423 }
19424 }
19425 <?php
19426
19427
19428
19429
19430
19431
19432
19433
19434
19435
19436
19437 namespace Composer\EventDispatcher;
19438
19439
19440
19441
19442
19443
19444 class Event
19445 {
19446
19447
19448
19449 protected $name;
19450
19451
19452
19453
19454 protected $args;
19455
19456
19457
19458
19459 protected $flags;
19460
19461
19462
19463
19464 private $propagationStopped = false;
19465
19466
19467
19468
19469
19470
19471
19472
19473 public function __construct($name, array $args = array(), array $flags = array())
19474 {
19475 $this->name = $name;
19476 $this->args = $args;
19477 $this->flags = $flags;
19478 }
19479
19480
19481
19482
19483
19484
19485 public function getName()
19486 {
19487 return $this->name;
19488 }
19489
19490
19491
19492
19493
19494
19495 public function getArguments()
19496 {
19497 return $this->args;
19498 }
19499
19500
19501
19502
19503
19504
19505 public function getFlags()
19506 {
19507 return $this->flags;
19508 }
19509
19510
19511
19512
19513
19514
19515 public function isPropagationStopped()
19516 {
19517 return $this->propagationStopped;
19518 }
19519
19520
19521
19522
19523 public function stopPropagation()
19524 {
19525 $this->propagationStopped = true;
19526 }
19527 }
19528 <?php
19529
19530
19531
19532
19533
19534
19535
19536
19537
19538
19539
19540 namespace Composer\EventDispatcher;
19541
19542 use Composer\DependencyResolver\PolicyInterface;
19543 use Composer\DependencyResolver\Pool;
19544 use Composer\DependencyResolver\Request;
19545 use Composer\Installer\InstallerEvent;
19546 use Composer\IO\IOInterface;
19547 use Composer\Composer;
19548 use Composer\DependencyResolver\Operation\OperationInterface;
19549 use Composer\Repository\CompositeRepository;
19550 use Composer\Script;
19551 use Composer\Installer\PackageEvent;
19552 use Composer\Installer\BinaryInstaller;
19553 use Composer\Util\ProcessExecutor;
19554 use Composer\Script\Event as ScriptEvent;
19555 use Symfony\Component\Process\PhpExecutableFinder;
19556
19557
19558
19559
19560
19561
19562
19563
19564
19565
19566
19567
19568
19569
19570 class EventDispatcher
19571 {
19572 protected $composer;
19573 protected $io;
19574 protected $loader;
19575 protected $process;
19576 protected $listeners;
19577 private $eventStack;
19578
19579
19580
19581
19582
19583
19584
19585
19586 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
19587 {
19588 $this->composer = $composer;
19589 $this->io = $io;
19590 $this->process = $process ?: new ProcessExecutor($io);
19591 $this->eventStack = array();
19592 }
19593
19594
19595
19596
19597
19598
19599
19600
19601
19602 public function dispatch($eventName, Event $event = null)
19603 {
19604 if (null === $event) {
19605 $event = new Event($eventName);
19606 }
19607
19608 return $this->doDispatch($event);
19609 }
19610
19611
19612
19613
19614
19615
19616
19617
19618
19619
19620
19621 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
19622 {
19623 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
19624 }
19625
19626
19627
19628
19629
19630
19631
19632
19633
19634
19635
19636
19637
19638
19639
19640
19641 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
19642 {
19643 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
19644 }
19645
19646
19647
19648
19649
19650
19651
19652
19653
19654
19655
19656
19657
19658
19659
19660 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
19661 {
19662 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
19663 }
19664
19665
19666
19667
19668
19669
19670
19671
19672
19673 protected function doDispatch(Event $event)
19674 {
19675 $listeners = $this->getListeners($event);
19676
19677 $this->pushEvent($event);
19678
19679 $return = 0;
19680 foreach ($listeners as $callable) {
19681
19682 $this->ensureBinDirIsInPath();
19683
19684 if (!is_string($callable)) {
19685 if (!is_callable($callable)) {
19686 $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
19687
19688 throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
19689 }
19690 $event = $this->checkListenerExpectedEvent($callable, $event);
19691 $return = false === call_user_func($callable, $event) ? 1 : 0;
19692 } elseif ($this->isComposerScript($callable)) {
19693 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
19694
19695 $script = explode(' ', substr($callable, 1));
19696 $scriptName = $script[0];
19697 unset($script[0]);
19698
19699 $args = array_merge($script, $event->getArguments());
19700 $flags = $event->getFlags();
19701 if (substr($callable, 0, 10) === '@composer ') {
19702 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
19703 if (0 !== ($exitCode = $this->process->execute($exec))) {
19704 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
19705
19706 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
19707 }
19708 } else {
19709 if (!$this->getListeners(new Event($scriptName))) {
19710 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
19711 }
19712
19713 try {
19714 $scriptEvent = new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags);
19715 $scriptEvent->setOriginatingEvent($event);
19716 $return = $this->dispatch($scriptName, $scriptEvent);
19717 } catch (ScriptExecutionException $e) {
19718 $this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), true, IOInterface::QUIET);
19719 throw $e;
19720 }
19721 }
19722 } elseif ($this->isPhpScript($callable)) {
19723 $className = substr($callable, 0, strpos($callable, '::'));
19724 $methodName = substr($callable, strpos($callable, '::') + 2);
19725
19726 if (!class_exists($className)) {
19727 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
19728 continue;
19729 }
19730 if (!is_callable($callable)) {
19731 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
19732 continue;
19733 }
19734
19735 try {
19736 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
19737 } catch (\Exception $e) {
19738 $message = "Script %s handling the %s event terminated with an exception";
19739 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
19740 throw $e;
19741 }
19742 } else {
19743 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
19744 $exec = $callable . ($args === '' ? '' : ' '.$args);
19745 if ($this->io->isVerbose()) {
19746 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
19747 } else {
19748 $this->io->writeError(sprintf('> %s', $exec));
19749 }
19750
19751 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
19752 if ($possibleLocalBinaries) {
19753 foreach ($possibleLocalBinaries as $localExec) {
19754 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
19755 $caller = BinaryInstaller::determineBinaryCaller($localExec);
19756 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
19757 break;
19758 }
19759 }
19760 }
19761
19762 if (substr($exec, 0, 8) === '@putenv ') {
19763 putenv(substr($exec, 8));
19764 list($var, $value) = explode('=', substr($exec, 8), 2);
19765 $_SERVER[$var] = $value;
19766
19767 continue;
19768 } elseif (substr($exec, 0, 5) === '@php ') {
19769 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
19770 } else {
19771 $finder = new PhpExecutableFinder();
19772 $phpPath = $finder->find(false);
19773 if ($phpPath) {
19774 $_SERVER['PHP_BINARY'] = $phpPath;
19775 putenv('PHP_BINARY=' . $_SERVER['PHP_BINARY']);
19776 }
19777 }
19778
19779
19780
19781
19782 if (substr($exec, 0, 9) === 'composer ') {
19783 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($exec, 8);
19784 }
19785
19786 if (0 !== ($exitCode = $this->process->execute($exec))) {
19787 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
19788
19789 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
19790 }
19791 }
19792
19793 if ($event->isPropagationStopped()) {
19794 break;
19795 }
19796 }
19797
19798 $this->popEvent();
19799
19800 return $return;
19801 }
19802
19803 protected function getPhpExecCommand()
19804 {
19805 $finder = new PhpExecutableFinder();
19806 $phpPath = $finder->find(false);
19807 if (!$phpPath) {
19808 throw new \RuntimeException('Failed to locate PHP binary to execute '.$phpPath);
19809 }
19810 $phpArgs = $finder->findArguments();
19811 $phpArgs = $phpArgs ? ' ' . implode(' ', $phpArgs) : '';
19812 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
19813 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
19814 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
19815
19816 return ProcessExecutor::escape($phpPath) . $phpArgs . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
19817 }
19818
19819
19820
19821
19822
19823
19824 protected function executeEventPhpScript($className, $methodName, Event $event)
19825 {
19826 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
19827
19828 if ($this->io->isVerbose()) {
19829 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
19830 } else {
19831 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
19832 }
19833
19834 return $className::$methodName($event);
19835 }
19836
19837
19838
19839
19840
19841
19842 protected function checkListenerExpectedEvent($target, Event $event)
19843 {
19844 if (in_array($event->getName(), array(
19845 'init',
19846 'command',
19847 'pre-file-download',
19848 ), true)) {
19849 return $event;
19850 }
19851
19852 try {
19853 $reflected = new \ReflectionParameter($target, 0);
19854 } catch (\Exception $e) {
19855 return $event;
19856 }
19857
19858 $expected = null;
19859 $isClass = false;
19860 if (\PHP_VERSION_ID >= 70000) {
19861 $reflectionType = $reflected->getType();
19862 if ($reflectionType) {
19863 $expected = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string)$reflectionType;
19864 $isClass = !$reflectionType->isBuiltin();
19865 }
19866 } else {
19867 $expected = $reflected->getClass() ? $reflected->getClass()->getName() : null;
19868 $isClass = null !== $expected;
19869 }
19870
19871 if (!$isClass) {
19872 return $event;
19873 }
19874
19875
19876 if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
19877 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);
19878 $event = new \Composer\Script\CommandEvent(
19879 $event->getName(),
19880 $event->getComposer(),
19881 $event->getIO(),
19882 $event->isDevMode(),
19883 $event->getArguments()
19884 );
19885 }
19886 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
19887 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);
19888 $event = new \Composer\Script\PackageEvent(
19889 $event->getName(),
19890 $event->getComposer(),
19891 $event->getIO(),
19892 $event->isDevMode(),
19893 $event->getPolicy(),
19894 $event->getPool(),
19895 $event->getInstalledRepo(),
19896 $event->getRequest(),
19897 $event->getOperations(),
19898 $event->getOperation()
19899 );
19900 }
19901 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
19902 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);
19903 $event = new \Composer\Script\Event(
19904 $event->getName(),
19905 $event->getComposer(),
19906 $event->getIO(),
19907 $event->isDevMode(),
19908 $event->getArguments(),
19909 $event->getFlags()
19910 );
19911 }
19912
19913 return $event;
19914 }
19915
19916 private function serializeCallback($cb)
19917 {
19918 if (is_array($cb) && count($cb) === 2) {
19919 if (is_object($cb[0])) {
19920 $cb[0] = get_class($cb[0]);
19921 }
19922 if (is_string($cb[0]) && is_string($cb[1])) {
19923 $cb = implode('::', $cb);
19924 }
19925 }
19926 if (is_string($cb)) {
19927 return $cb;
19928 }
19929
19930 return var_export($cb, true);
19931 }
19932
19933
19934
19935
19936
19937
19938
19939
19940 public function addListener($eventName, $listener, $priority = 0)
19941 {
19942 $this->listeners[$eventName][$priority][] = $listener;
19943 }
19944
19945
19946
19947
19948
19949
19950
19951
19952 public function addSubscriber(EventSubscriberInterface $subscriber)
19953 {
19954 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
19955 if (is_string($params)) {
19956 $this->addListener($eventName, array($subscriber, $params));
19957 } elseif (is_string($params[0])) {
19958 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
19959 } else {
19960 foreach ($params as $listener) {
19961 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
19962 }
19963 }
19964 }
19965 }
19966
19967
19968
19969
19970
19971
19972
19973 protected function getListeners(Event $event)
19974 {
19975 $scriptListeners = $this->getScriptListeners($event);
19976
19977 if (!isset($this->listeners[$event->getName()][0])) {
19978 $this->listeners[$event->getName()][0] = array();
19979 }
19980 krsort($this->listeners[$event->getName()]);
19981
19982 $listeners = $this->listeners;
19983 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
19984
19985 return call_user_func_array('array_merge', $listeners[$event->getName()]);
19986 }
19987
19988
19989
19990
19991
19992
19993
19994 public function hasEventListeners(Event $event)
19995 {
19996 $listeners = $this->getListeners($event);
19997
19998 return count($listeners) > 0;
19999 }
20000
20001
20002
20003
20004
20005
20006
20007 protected function getScriptListeners(Event $event)
20008 {
20009 $package = $this->composer->getPackage();
20010 $scripts = $package->getScripts();
20011
20012 if (empty($scripts[$event->getName()])) {
20013 return array();
20014 }
20015
20016 if ($this->loader) {
20017 $this->loader->unregister();
20018 }
20019
20020 $generator = $this->composer->getAutoloadGenerator();
20021 if ($event instanceof ScriptEvent) {
20022 $generator->setDevMode($event->isDevMode());
20023 }
20024
20025 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
20026 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
20027 $map = $generator->parseAutoloads($packageMap, $package);
20028 $this->loader = $generator->createLoader($map);
20029 $this->loader->register();
20030
20031 return $scripts[$event->getName()];
20032 }
20033
20034
20035
20036
20037
20038
20039
20040 protected function isPhpScript($callable)
20041 {
20042 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
20043 }
20044
20045
20046
20047
20048
20049
20050
20051 protected function isComposerScript($callable)
20052 {
20053 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5) && '@putenv ' !== substr($callable, 0, 8);
20054 }
20055
20056
20057
20058
20059
20060
20061
20062
20063 protected function pushEvent(Event $event)
20064 {
20065 $eventName = $event->getName();
20066 if (in_array($eventName, $this->eventStack)) {
20067 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
20068 }
20069
20070 return array_push($this->eventStack, $eventName);
20071 }
20072
20073
20074
20075
20076
20077
20078 protected function popEvent()
20079 {
20080 return array_pop($this->eventStack);
20081 }
20082
20083 private function ensureBinDirIsInPath()
20084 {
20085 $pathStr = 'PATH';
20086 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
20087 $pathStr = 'Path';
20088 }
20089
20090
20091 $binDir = $this->composer->getConfig()->get('bin-dir');
20092 if (is_dir($binDir)) {
20093 $binDir = realpath($binDir);
20094 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
20095 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
20096 putenv($pathStr.'='.$_SERVER[$pathStr]);
20097 }
20098 }
20099 }
20100 }
20101 <?php
20102
20103
20104
20105
20106
20107
20108
20109
20110
20111
20112
20113 namespace Composer\EventDispatcher;
20114
20115
20116
20117
20118
20119
20120
20121
20122
20123
20124
20125
20126
20127 interface EventSubscriberInterface
20128 {
20129
20130
20131
20132
20133
20134
20135
20136
20137
20138
20139
20140
20141
20142
20143
20144
20145
20146
20147 public static function getSubscribedEvents();
20148 }
20149 <?php
20150
20151
20152
20153
20154
20155
20156
20157
20158
20159
20160
20161 namespace Composer\EventDispatcher;
20162
20163
20164
20165
20166 class ScriptExecutionException extends \RuntimeException
20167 {
20168 }
20169 <?php
20170
20171
20172
20173
20174
20175
20176
20177
20178
20179
20180
20181 namespace Composer\Exception;
20182
20183
20184
20185
20186 class NoSslException extends \RuntimeException
20187 {
20188 }
20189 <?php
20190
20191
20192
20193
20194
20195
20196
20197
20198
20199
20200
20201 namespace Composer;
20202
20203 use Composer\Config\JsonConfigSource;
20204 use Composer\Json\JsonFile;
20205 use Composer\IO\IOInterface;
20206 use Composer\Package\Archiver;
20207 use Composer\Package\Version\VersionGuesser;
20208 use Composer\Repository\RepositoryManager;
20209 use Composer\Repository\RepositoryFactory;
20210 use Composer\Repository\WritableRepositoryInterface;
20211 use Composer\Util\Filesystem;
20212 use Composer\Util\Platform;
20213 use Composer\Util\ProcessExecutor;
20214 use Composer\Util\RemoteFilesystem;
20215 use Composer\Util\Silencer;
20216 use Composer\Plugin\PluginEvents;
20217 use Composer\EventDispatcher\Event;
20218 use Seld\JsonLint\DuplicateKeyException;
20219 use Symfony\Component\Console\Formatter\OutputFormatter;
20220 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
20221 use Symfony\Component\Console\Output\ConsoleOutput;
20222 use Composer\EventDispatcher\EventDispatcher;
20223 use Composer\Autoload\AutoloadGenerator;
20224 use Composer\Package\Version\VersionParser;
20225 use Composer\Downloader\TransportException;
20226 use Seld\JsonLint\JsonParser;
20227
20228
20229
20230
20231
20232
20233
20234
20235
20236 class Factory
20237 {
20238
20239
20240
20241
20242 protected static function getHomeDir()
20243 {
20244 $home = getenv('COMPOSER_HOME');
20245 if ($home) {
20246 return $home;
20247 }
20248
20249 if (Platform::isWindows()) {
20250 if (!getenv('APPDATA')) {
20251 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
20252 }
20253
20254 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
20255 }
20256
20257 $userDir = self::getUserDir();
20258 if (is_dir($userDir . '/.composer')) {
20259 return $userDir . '/.composer';
20260 }
20261
20262 if (self::useXdg()) {
20263
20264 $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
20265
20266 return $xdgConfig . '/composer';
20267 }
20268
20269 return $userDir . '/.composer';
20270 }
20271
20272
20273
20274
20275
20276 protected static function getCacheDir($home)
20277 {
20278 $cacheDir = getenv('COMPOSER_CACHE_DIR');
20279 if ($cacheDir) {
20280 return $cacheDir;
20281 }
20282
20283 $homeEnv = getenv('COMPOSER_HOME');
20284 if ($homeEnv) {
20285 return $homeEnv . '/cache';
20286 }
20287
20288 if (Platform::isWindows()) {
20289 if ($cacheDir = getenv('LOCALAPPDATA')) {
20290 $cacheDir .= '/Composer';
20291 } else {
20292 $cacheDir = $home . '/cache';
20293 }
20294
20295 return rtrim(strtr($cacheDir, '\\', '/'), '/');
20296 }
20297
20298 $userDir = self::getUserDir();
20299 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
20300 return $home . '/cache';
20301 }
20302
20303 if (self::useXdg()) {
20304 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
20305
20306 return $xdgCache . '/composer';
20307 }
20308
20309 return $home . '/cache';
20310 }
20311
20312
20313
20314
20315
20316 protected static function getDataDir($home)
20317 {
20318 $homeEnv = getenv('COMPOSER_HOME');
20319 if ($homeEnv) {
20320 return $homeEnv;
20321 }
20322
20323 if (Platform::isWindows()) {
20324 return strtr($home, '\\', '/');
20325 }
20326
20327 $userDir = self::getUserDir();
20328 if ($home !== $userDir . '/.composer' && self::useXdg()) {
20329 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
20330
20331 return $xdgData . '/composer';
20332 }
20333
20334 return $home;
20335 }
20336
20337
20338
20339
20340
20341 public static function createConfig(IOInterface $io = null, $cwd = null)
20342 {
20343 $cwd = $cwd ?: getcwd();
20344
20345 $config = new Config(true, $cwd);
20346
20347
20348 $home = self::getHomeDir();
20349 $config->merge(array('config' => array(
20350 'home' => $home,
20351 'cache-dir' => self::getCacheDir($home),
20352 'data-dir' => self::getDataDir($home),
20353 )));
20354
20355
20356 $file = new JsonFile($config->get('home').'/config.json');
20357 if ($file->exists()) {
20358 if ($io && $io->isDebug()) {
20359 $io->writeError('Loading config file ' . $file->getPath());
20360 }
20361 $config->merge($file->read());
20362 }
20363 $config->setConfigSource(new JsonConfigSource($file));
20364
20365 $htaccessProtect = (bool) $config->get('htaccess-protect');
20366 if ($htaccessProtect) {
20367
20368
20369
20370 $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
20371 foreach ($dirs as $dir) {
20372 if (!file_exists($dir . '/.htaccess')) {
20373 if (!is_dir($dir)) {
20374 Silencer::call('mkdir', $dir, 0777, true);
20375 }
20376 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
20377 }
20378 }
20379 }
20380
20381
20382 $file = new JsonFile($config->get('home').'/auth.json');
20383 if ($file->exists()) {
20384 if ($io && $io->isDebug()) {
20385 $io->writeError('Loading config file ' . $file->getPath());
20386 }
20387 $config->merge(array('config' => $file->read()));
20388 }
20389 $config->setAuthConfigSource(new JsonConfigSource($file, true));
20390
20391
20392 if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
20393 $authData = json_decode($composerAuthEnv, true);
20394
20395 if (null === $authData) {
20396 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
20397 }
20398
20399 if ($io && $io->isDebug()) {
20400 $io->writeError('Loading auth config from COMPOSER_AUTH');
20401 }
20402 $config->merge(array('config' => $authData));
20403 }
20404
20405 return $config;
20406 }
20407
20408 public static function getComposerFile()
20409 {
20410 return trim(getenv('COMPOSER')) ?: './composer.json';
20411 }
20412
20413 public static function createAdditionalStyles()
20414 {
20415 return array(
20416 'highlight' => new OutputFormatterStyle('red'),
20417 'warning' => new OutputFormatterStyle('black', 'yellow'),
20418 );
20419 }
20420
20421
20422
20423
20424
20425
20426 public static function createOutput()
20427 {
20428 $styles = self::createAdditionalStyles();
20429 $formatter = new OutputFormatter(false, $styles);
20430
20431 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
20432 }
20433
20434
20435
20436
20437 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
20438 {
20439 return RepositoryFactory::defaultRepos($io, $config, $rm);
20440 }
20441
20442
20443
20444
20445
20446
20447
20448
20449
20450
20451
20452
20453
20454 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
20455 {
20456 $cwd = $cwd ?: getcwd();
20457
20458
20459 if (null === $localConfig) {
20460 $localConfig = static::getComposerFile();
20461 }
20462
20463 if (is_string($localConfig)) {
20464 $composerFile = $localConfig;
20465
20466 $file = new JsonFile($localConfig, null, $io);
20467
20468 if (!$file->exists()) {
20469 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
20470 $message = 'Composer could not find a composer.json file in '.$cwd;
20471 } else {
20472 $message = 'Composer could not find the config file: '.$localConfig;
20473 }
20474 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
20475 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
20476 }
20477
20478 $file->validateSchema(JsonFile::LAX_SCHEMA);
20479 $jsonParser = new JsonParser;
20480 try {
20481 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
20482 } catch (DuplicateKeyException $e) {
20483 $details = $e->getDetails();
20484 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
20485 }
20486
20487 $localConfig = $file->read();
20488 }
20489
20490
20491 $config = static::createConfig($io, $cwd);
20492 $config->merge($localConfig);
20493 if (isset($composerFile)) {
20494 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
20495 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
20496
20497 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
20498 if ($localAuthFile->exists()) {
20499 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
20500 $config->merge(array('config' => $localAuthFile->read()));
20501 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
20502 }
20503 }
20504
20505 $vendorDir = $config->get('vendor-dir');
20506
20507
20508 $composer = new Composer();
20509 $composer->setConfig($config);
20510
20511 if ($fullLoad) {
20512
20513 $io->loadConfiguration($config);
20514 }
20515
20516 $rfs = self::createRemoteFilesystem($io, $config);
20517
20518
20519 $dispatcher = new EventDispatcher($composer, $io);
20520 $composer->setEventDispatcher($dispatcher);
20521
20522
20523 $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
20524 $composer->setRepositoryManager($rm);
20525
20526
20527 $this->addLocalRepository($io, $rm, $vendorDir);
20528
20529
20530
20531 if (!$fullLoad && !isset($localConfig['version'])) {
20532 $localConfig['version'] = '1.0.0';
20533 }
20534
20535
20536 $parser = new VersionParser;
20537 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
20538 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
20539 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
20540 $composer->setPackage($package);
20541
20542
20543 $im = $this->createInstallationManager();
20544 $composer->setInstallationManager($im);
20545
20546 if ($fullLoad) {
20547
20548 $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
20549 $composer->setDownloadManager($dm);
20550
20551
20552 $generator = new AutoloadGenerator($dispatcher, $io);
20553 $composer->setAutoloadGenerator($generator);
20554
20555
20556 $am = $this->createArchiveManager($config, $dm);
20557 $composer->setArchiveManager($am);
20558 }
20559
20560
20561 $this->createDefaultInstallers($im, $composer, $io);
20562
20563 if ($fullLoad) {
20564 $globalComposer = null;
20565 if (realpath($config->get('home')) !== $cwd) {
20566 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
20567 }
20568
20569 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
20570 $composer->setPluginManager($pm);
20571
20572 $pm->loadInstalledPlugins();
20573 }
20574
20575
20576 if ($fullLoad && isset($composerFile)) {
20577 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
20578 ? substr($composerFile, 0, -4).'lock'
20579 : $composerFile . '.lock';
20580
20581 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
20582 $composer->setLocker($locker);
20583 }
20584
20585 if ($fullLoad) {
20586 $initEvent = new Event(PluginEvents::INIT);
20587 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
20588
20589
20590
20591 if ($rm->getLocalRepository()) {
20592 $this->purgePackages($rm->getLocalRepository(), $im);
20593 }
20594 }
20595
20596 return $composer;
20597 }
20598
20599
20600
20601
20602
20603
20604 public static function createGlobal(IOInterface $io, $disablePlugins = false)
20605 {
20606 $factory = new static();
20607
20608 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
20609 }
20610
20611
20612
20613
20614
20615 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
20616 {
20617 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
20618 }
20619
20620
20621
20622
20623
20624 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
20625 {
20626 $composer = null;
20627 try {
20628 $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
20629 } catch (\Exception $e) {
20630 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
20631 }
20632
20633 return $composer;
20634 }
20635
20636
20637
20638
20639
20640
20641
20642 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
20643 {
20644 $cache = null;
20645 if ($config->get('cache-files-ttl') > 0) {
20646 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
20647 }
20648
20649 $dm = new Downloader\DownloadManager($io);
20650 switch ($preferred = $config->get('preferred-install')) {
20651 case 'dist':
20652 $dm->setPreferDist(true);
20653 break;
20654 case 'source':
20655 $dm->setPreferSource(true);
20656 break;
20657 case 'auto':
20658 default:
20659
20660 break;
20661 }
20662
20663 if (is_array($preferred)) {
20664 $dm->setPreferences($preferred);
20665 }
20666
20667 $executor = new ProcessExecutor($io);
20668 $fs = new Filesystem($executor);
20669
20670 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
20671 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
20672 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
20673 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
20674 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
20675 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20676 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20677 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20678 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20679 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20680 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20681 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20682 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20683
20684 return $dm;
20685 }
20686
20687
20688
20689
20690
20691
20692 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
20693 {
20694 if (null === $dm) {
20695 $io = new IO\NullIO();
20696 $io->loadConfiguration($config);
20697 $dm = $this->createDownloadManager($io, $config);
20698 }
20699
20700 $am = new Archiver\ArchiveManager($dm);
20701 $am->addArchiver(new Archiver\ZipArchiver);
20702 $am->addArchiver(new Archiver\PharArchiver);
20703
20704 return $am;
20705 }
20706
20707
20708
20709
20710
20711
20712
20713
20714 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
20715 {
20716 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
20717 }
20718
20719
20720
20721
20722 protected function createInstallationManager()
20723 {
20724 return new Installer\InstallationManager();
20725 }
20726
20727
20728
20729
20730
20731
20732 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
20733 {
20734 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
20735 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
20736 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
20737 $im->addInstaller(new Installer\MetapackageInstaller($io));
20738 }
20739
20740
20741
20742
20743
20744 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
20745 {
20746 foreach ($repo->getPackages() as $package) {
20747 if (!$im->isPackageInstalled($repo, $package)) {
20748 $repo->removePackage($package);
20749 }
20750 }
20751 }
20752
20753
20754
20755
20756
20757
20758
20759
20760 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
20761 {
20762 $factory = new static();
20763
20764 return $factory->createComposer($io, $config, $disablePlugins);
20765 }
20766
20767
20768
20769
20770
20771
20772
20773 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
20774 {
20775 static $warned = false;
20776 $disableTls = false;
20777
20778 if (isset($_SERVER['argv']) && in_array('disable-tls', $_SERVER['argv']) && (in_array('conf', $_SERVER['argv']) || in_array('config', $_SERVER['argv']))) {
20779 $warned = true;
20780 $disableTls = !extension_loaded('openssl');
20781 } elseif ($config && $config->get('disable-tls') === true) {
20782 if (!$warned) {
20783 $io->writeError('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
20784 }
20785 $warned = true;
20786 $disableTls = true;
20787 } elseif (!extension_loaded('openssl')) {
20788 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
20789 . '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.');
20790 }
20791 $remoteFilesystemOptions = array();
20792 if ($disableTls === false) {
20793 if ($config && $config->get('cafile')) {
20794 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
20795 }
20796 if ($config && $config->get('capath')) {
20797 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
20798 }
20799 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
20800 }
20801 try {
20802 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
20803 } catch (TransportException $e) {
20804 if (false !== strpos($e->getMessage(), 'cafile')) {
20805 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
20806 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
20807 if (PHP_VERSION_ID < 50600) {
20808 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
20809 }
20810 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
20811 }
20812 throw $e;
20813 }
20814
20815 return $remoteFilesystem;
20816 }
20817
20818
20819
20820
20821 private static function useXdg()
20822 {
20823 foreach (array_keys($_SERVER) as $key) {
20824 if (substr($key, 0, 4) === 'XDG_') {
20825 return true;
20826 }
20827 }
20828
20829 return false;
20830 }
20831
20832
20833
20834
20835
20836 private static function getUserDir()
20837 {
20838 $home = getenv('HOME');
20839 if (!$home) {
20840 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
20841 }
20842
20843 return rtrim(strtr($home, '\\', '/'), '/');
20844 }
20845 }
20846 <?php
20847
20848
20849
20850
20851
20852
20853
20854
20855
20856
20857
20858 namespace Composer\IO;
20859
20860 use Composer\Config;
20861 use Composer\Util\ProcessExecutor;
20862 use Psr\Log\LoggerInterface;
20863 use Psr\Log\LogLevel;
20864
20865 abstract class BaseIO implements IOInterface, LoggerInterface
20866 {
20867 protected $authentications = array();
20868
20869
20870
20871
20872 public function getAuthentications()
20873 {
20874 return $this->authentications;
20875 }
20876
20877
20878
20879
20880 public function resetAuthentications()
20881 {
20882 $this->authentications = array();
20883 }
20884
20885
20886
20887
20888 public function hasAuthentication($repositoryName)
20889 {
20890 return isset($this->authentications[$repositoryName]);
20891 }
20892
20893
20894
20895
20896 public function getAuthentication($repositoryName)
20897 {
20898 if (isset($this->authentications[$repositoryName])) {
20899 return $this->authentications[$repositoryName];
20900 }
20901
20902 return array('username' => null, 'password' => null);
20903 }
20904
20905
20906
20907
20908 public function setAuthentication($repositoryName, $username, $password = null)
20909 {
20910 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
20911 }
20912
20913
20914
20915
20916 public function writeRaw($messages, $newline = true, $verbosity = self::NORMAL)
20917 {
20918 $this->write($messages, $newline, $verbosity);
20919 }
20920
20921
20922
20923
20924 public function writeErrorRaw($messages, $newline = true, $verbosity = self::NORMAL)
20925 {
20926 $this->writeError($messages, $newline, $verbosity);
20927 }
20928
20929
20930
20931
20932
20933
20934
20935
20936 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
20937 {
20938 if ($this->hasAuthentication($repositoryName)) {
20939 $auth = $this->getAuthentication($repositoryName);
20940 if ($auth['username'] === $username && $auth['password'] === $password) {
20941 return;
20942 }
20943
20944 $this->writeError(
20945 sprintf(
20946 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
20947 $repositoryName
20948 )
20949 );
20950 }
20951 $this->setAuthentication($repositoryName, $username, $password);
20952 }
20953
20954
20955
20956
20957 public function loadConfiguration(Config $config)
20958 {
20959 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
20960 $githubOauth = $config->get('github-oauth') ?: array();
20961 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
20962 $gitlabToken = $config->get('gitlab-token') ?: array();
20963 $httpBasic = $config->get('http-basic') ?: array();
20964 $bearerToken = $config->get('bearer') ?: array();
20965
20966
20967
20968 foreach ($bitbucketOauth as $domain => $cred) {
20969 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
20970 }
20971
20972 foreach ($githubOauth as $domain => $token) {
20973
20974
20975 if (!preg_match('{^[.A-Za-z0-9_]+$}', $token)) {
20976 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
20977 }
20978 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
20979 }
20980
20981 foreach ($gitlabOauth as $domain => $token) {
20982 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
20983 }
20984
20985 foreach ($gitlabToken as $domain => $token) {
20986 $this->checkAndSetAuthentication($domain, $token, 'private-token');
20987 }
20988
20989
20990 foreach ($httpBasic as $domain => $cred) {
20991 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
20992 }
20993
20994 foreach ($bearerToken as $domain => $token) {
20995 $this->checkAndSetAuthentication($domain, $token, 'bearer');
20996 }
20997
20998
20999 ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
21000 }
21001
21002
21003
21004
21005
21006
21007
21008
21009 public function emergency($message, array $context = array())
21010 {
21011 return $this->log(LogLevel::EMERGENCY, $message, $context);
21012 }
21013
21014
21015
21016
21017
21018
21019
21020
21021
21022
21023
21024 public function alert($message, array $context = array())
21025 {
21026 return $this->log(LogLevel::ALERT, $message, $context);
21027 }
21028
21029
21030
21031
21032
21033
21034
21035
21036
21037
21038 public function critical($message, array $context = array())
21039 {
21040 return $this->log(LogLevel::CRITICAL, $message, $context);
21041 }
21042
21043
21044
21045
21046
21047
21048
21049
21050
21051 public function error($message, array $context = array())
21052 {
21053 return $this->log(LogLevel::ERROR, $message, $context);
21054 }
21055
21056
21057
21058
21059
21060
21061
21062
21063
21064
21065
21066 public function warning($message, array $context = array())
21067 {
21068 return $this->log(LogLevel::WARNING, $message, $context);
21069 }
21070
21071
21072
21073
21074
21075
21076
21077
21078 public function notice($message, array $context = array())
21079 {
21080 return $this->log(LogLevel::NOTICE, $message, $context);
21081 }
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092 public function info($message, array $context = array())
21093 {
21094 return $this->log(LogLevel::INFO, $message, $context);
21095 }
21096
21097
21098
21099
21100
21101
21102
21103
21104 public function debug($message, array $context = array())
21105 {
21106 return $this->log(LogLevel::DEBUG, $message, $context);
21107 }
21108
21109
21110
21111
21112
21113
21114
21115
21116
21117 public function log($level, $message, array $context = array())
21118 {
21119 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
21120 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
21121 } elseif ($level === LogLevel::WARNING) {
21122 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
21123 } elseif ($level === LogLevel::NOTICE) {
21124 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
21125 } elseif ($level === LogLevel::INFO) {
21126 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
21127 } else {
21128 $this->writeError($message, true, self::DEBUG);
21129 }
21130 }
21131 }
21132 <?php
21133
21134
21135
21136
21137
21138
21139
21140
21141
21142
21143
21144 namespace Composer\IO;
21145
21146 use Symfony\Component\Console\Helper\QuestionHelper;
21147 use Symfony\Component\Console\Output\StreamOutput;
21148 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
21149 use Symfony\Component\Console\Input\StreamableInputInterface;
21150 use Symfony\Component\Console\Input\StringInput;
21151 use Symfony\Component\Console\Helper\HelperSet;
21152
21153
21154
21155
21156 class BufferIO extends ConsoleIO
21157 {
21158
21159
21160
21161
21162
21163 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
21164 {
21165 $input = new StringInput($input);
21166 $input->setInteractive(false);
21167
21168 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
21169
21170 parent::__construct($input, $output, new HelperSet(array(
21171 new QuestionHelper(),
21172 )));
21173 }
21174
21175 public function getOutput()
21176 {
21177 fseek($this->output->getStream(), 0);
21178
21179 $output = stream_get_contents($this->output->getStream());
21180
21181 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
21182 $pre = strip_tags($matches[1]);
21183
21184 if (strlen($pre) === strlen($matches[2])) {
21185 return '';
21186 }
21187
21188
21189 return rtrim($matches[1])."\n";
21190 }, $output);
21191
21192 return $output;
21193 }
21194
21195 public function setUserInputs(array $inputs)
21196 {
21197 if (!$this->input instanceof StreamableInputInterface) {
21198 throw new \RuntimeException('Setting the user inputs requires at least the version 3.2 of the symfony/console component.');
21199 }
21200
21201 $this->input->setStream($this->createStream($inputs));
21202 $this->input->setInteractive(true);
21203 }
21204
21205 private function createStream(array $inputs)
21206 {
21207 $stream = fopen('php://memory', 'r+', false);
21208
21209 foreach ($inputs as $input) {
21210 fwrite($stream, $input.PHP_EOL);
21211 }
21212
21213 rewind($stream);
21214
21215 return $stream;
21216 }
21217 }
21218 <?php
21219
21220
21221
21222
21223
21224
21225
21226
21227
21228
21229
21230 namespace Composer\IO;
21231
21232 use Composer\Question\StrictConfirmationQuestion;
21233 use Symfony\Component\Console\Helper\HelperSet;
21234 use Symfony\Component\Console\Input\InputInterface;
21235 use Symfony\Component\Console\Output\ConsoleOutputInterface;
21236 use Symfony\Component\Console\Output\OutputInterface;
21237 use Symfony\Component\Console\Question\ChoiceQuestion;
21238 use Symfony\Component\Console\Question\Question;
21239
21240
21241
21242
21243
21244
21245
21246 class ConsoleIO extends BaseIO
21247 {
21248
21249 protected $input;
21250
21251 protected $output;
21252
21253 protected $helperSet;
21254
21255 protected $lastMessage;
21256
21257 protected $lastMessageErr;
21258
21259
21260 private $startTime;
21261
21262 private $verbosityMap;
21263
21264
21265
21266
21267
21268
21269
21270
21271 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
21272 {
21273 $this->input = $input;
21274 $this->output = $output;
21275 $this->helperSet = $helperSet;
21276 $this->verbosityMap = array(
21277 self::QUIET => OutputInterface::VERBOSITY_QUIET,
21278 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
21279 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
21280 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
21281 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
21282 );
21283 }
21284
21285
21286
21287
21288 public function enableDebugging($startTime)
21289 {
21290 $this->startTime = $startTime;
21291 }
21292
21293
21294
21295
21296 public function isInteractive()
21297 {
21298 return $this->input->isInteractive();
21299 }
21300
21301
21302
21303
21304 public function isDecorated()
21305 {
21306 return $this->output->isDecorated();
21307 }
21308
21309
21310
21311
21312 public function isVerbose()
21313 {
21314 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
21315 }
21316
21317
21318
21319
21320 public function isVeryVerbose()
21321 {
21322 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
21323 }
21324
21325
21326
21327
21328 public function isDebug()
21329 {
21330 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
21331 }
21332
21333
21334
21335
21336 public function write($messages, $newline = true, $verbosity = self::NORMAL)
21337 {
21338 $this->doWrite($messages, $newline, false, $verbosity);
21339 }
21340
21341
21342
21343
21344 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
21345 {
21346 $this->doWrite($messages, $newline, true, $verbosity);
21347 }
21348
21349
21350
21351
21352 public function writeRaw($messages, $newline = true, $verbosity = self::NORMAL)
21353 {
21354 $this->doWrite($messages, $newline, false, $verbosity, true);
21355 }
21356
21357
21358
21359
21360 public function writeErrorRaw($messages, $newline = true, $verbosity = self::NORMAL)
21361 {
21362 $this->doWrite($messages, $newline, true, $verbosity, true);
21363 }
21364
21365
21366
21367
21368
21369
21370
21371 private function doWrite($messages, $newline, $stderr, $verbosity, $raw = false)
21372 {
21373 $sfVerbosity = $this->verbosityMap[$verbosity];
21374 if ($sfVerbosity > $this->output->getVerbosity()) {
21375 return;
21376 }
21377
21378
21379
21380
21381 if (OutputInterface::VERBOSITY_QUIET === 0) {
21382 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
21383 }
21384
21385 if ($raw) {
21386 if ($sfVerbosity === OutputInterface::OUTPUT_NORMAL) {
21387 $sfVerbosity = OutputInterface::OUTPUT_RAW;
21388 } else {
21389 $sfVerbosity |= OutputInterface::OUTPUT_RAW;
21390 }
21391 }
21392
21393 if (null !== $this->startTime) {
21394 $memoryUsage = memory_get_usage() / 1024 / 1024;
21395 $timeSpent = microtime(true) - $this->startTime;
21396 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
21397 return sprintf('[%.1fMiB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
21398 }, (array) $messages);
21399 }
21400
21401 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
21402 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
21403 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
21404
21405 return;
21406 }
21407
21408 $this->output->write($messages, $newline, $sfVerbosity);
21409 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
21410 }
21411
21412
21413
21414
21415 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
21416 {
21417 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
21418 }
21419
21420
21421
21422
21423 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
21424 {
21425 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
21426 }
21427
21428
21429
21430
21431
21432
21433
21434
21435 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
21436 {
21437
21438 $messages = implode($newline ? "\n" : '', (array) $messages);
21439
21440
21441 if (!isset($size)) {
21442
21443 $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
21444 }
21445
21446 $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
21447
21448
21449 $this->doWrite($messages, false, $stderr, $verbosity);
21450
21451
21452
21453
21454 $fill = $size - strlen(strip_tags($messages));
21455 if ($fill > 0) {
21456
21457 $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
21458
21459 $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
21460 }
21461
21462 if ($newline) {
21463 $this->doWrite('', true, $stderr, $verbosity);
21464 }
21465
21466 if ($stderr) {
21467 $this->lastMessageErr = $messages;
21468 } else {
21469 $this->lastMessage = $messages;
21470 }
21471 }
21472
21473
21474
21475
21476 public function ask($question, $default = null)
21477 {
21478
21479 $helper = $this->helperSet->get('question');
21480 $question = new Question($question, $default);
21481
21482 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21483 }
21484
21485
21486
21487
21488 public function askConfirmation($question, $default = true)
21489 {
21490
21491 $helper = $this->helperSet->get('question');
21492 $question = new StrictConfirmationQuestion($question, $default);
21493
21494 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21495 }
21496
21497
21498
21499
21500 public function askAndValidate($question, $validator, $attempts = null, $default = null)
21501 {
21502
21503 $helper = $this->helperSet->get('question');
21504 $question = new Question($question, $default);
21505 $question->setValidator($validator);
21506 $question->setMaxAttempts($attempts);
21507
21508 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21509 }
21510
21511
21512
21513
21514 public function askAndHideAnswer($question)
21515 {
21516
21517 $helper = $this->helperSet->get('question');
21518 $question = new Question($question);
21519 $question->setHidden(true);
21520
21521 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21522 }
21523
21524
21525
21526
21527 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
21528 {
21529
21530 $helper = $this->helperSet->get('question');
21531 $question = new ChoiceQuestion($question, $choices, $default);
21532 $question->setMaxAttempts($attempts ?: null); 
21533 $question->setErrorMessage($errorMessage);
21534 $question->setMultiselect($multiselect);
21535
21536 $result = $helper->ask($this->input, $this->getErrorOutput(), $question);
21537
21538 if (!is_array($result)) {
21539 return (string) array_search($result, $choices, true);
21540 }
21541
21542 $results = array();
21543 foreach ($choices as $index => $choice) {
21544 if (in_array($choice, $result, true)) {
21545 $results[] = (string) $index;
21546 }
21547 }
21548
21549 return $results;
21550 }
21551
21552
21553
21554
21555 private function getErrorOutput()
21556 {
21557 if ($this->output instanceof ConsoleOutputInterface) {
21558 return $this->output->getErrorOutput();
21559 }
21560
21561 return $this->output;
21562 }
21563 }
21564 <?php
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576 namespace Composer\IO;
21577
21578 use Composer\Config;
21579
21580
21581
21582
21583
21584
21585 interface IOInterface
21586 {
21587 const QUIET = 1;
21588 const NORMAL = 2;
21589 const VERBOSE = 4;
21590 const VERY_VERBOSE = 8;
21591 const DEBUG = 16;
21592
21593
21594
21595
21596
21597
21598 public function isInteractive();
21599
21600
21601
21602
21603
21604
21605 public function isVerbose();
21606
21607
21608
21609
21610
21611
21612 public function isVeryVerbose();
21613
21614
21615
21616
21617
21618
21619 public function isDebug();
21620
21621
21622
21623
21624
21625
21626 public function isDecorated();
21627
21628
21629
21630
21631
21632
21633
21634
21635 public function write($messages, $newline = true, $verbosity = self::NORMAL);
21636
21637
21638
21639
21640
21641
21642
21643
21644 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
21645
21646
21647
21648
21649
21650
21651
21652
21653
21654 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
21655
21656
21657
21658
21659
21660
21661
21662
21663
21664 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
21665
21666
21667
21668
21669
21670
21671
21672
21673
21674
21675 public function ask($question, $default = null);
21676
21677
21678
21679
21680
21681
21682
21683
21684
21685
21686
21687 public function askConfirmation($question, $default = true);
21688
21689
21690
21691
21692
21693
21694
21695
21696
21697
21698
21699
21700
21701
21702
21703
21704 public function askAndValidate($question, $validator, $attempts = null, $default = null);
21705
21706
21707
21708
21709
21710
21711
21712
21713 public function askAndHideAnswer($question);
21714
21715
21716
21717
21718
21719
21720
21721
21722
21723
21724
21725
21726
21727
21728 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
21729
21730
21731
21732
21733
21734
21735 public function getAuthentications();
21736
21737
21738
21739
21740
21741
21742
21743
21744 public function hasAuthentication($repositoryName);
21745
21746
21747
21748
21749
21750
21751
21752
21753 public function getAuthentication($repositoryName);
21754
21755
21756
21757
21758
21759
21760
21761
21762 public function setAuthentication($repositoryName, $username, $password = null);
21763
21764
21765
21766
21767
21768
21769 public function loadConfiguration(Config $config);
21770 }
21771 <?php
21772
21773
21774
21775
21776
21777
21778
21779
21780
21781
21782
21783 namespace Composer\IO;
21784
21785
21786
21787
21788
21789
21790 class NullIO extends BaseIO
21791 {
21792
21793
21794
21795 public function isInteractive()
21796 {
21797 return false;
21798 }
21799
21800
21801
21802
21803 public function isVerbose()
21804 {
21805 return false;
21806 }
21807
21808
21809
21810
21811 public function isVeryVerbose()
21812 {
21813 return false;
21814 }
21815
21816
21817
21818
21819 public function isDebug()
21820 {
21821 return false;
21822 }
21823
21824
21825
21826
21827 public function isDecorated()
21828 {
21829 return false;
21830 }
21831
21832
21833
21834
21835 public function write($messages, $newline = true, $verbosity = self::NORMAL)
21836 {
21837 }
21838
21839
21840
21841
21842 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
21843 {
21844 }
21845
21846
21847
21848
21849 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
21850 {
21851 }
21852
21853
21854
21855
21856 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
21857 {
21858 }
21859
21860
21861
21862
21863 public function ask($question, $default = null)
21864 {
21865 return $default;
21866 }
21867
21868
21869
21870
21871 public function askConfirmation($question, $default = true)
21872 {
21873 return $default;
21874 }
21875
21876
21877
21878
21879 public function askAndValidate($question, $validator, $attempts = false, $default = null)
21880 {
21881 return $default;
21882 }
21883
21884
21885
21886
21887 public function askAndHideAnswer($question)
21888 {
21889 return null;
21890 }
21891
21892
21893
21894
21895 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
21896 {
21897 return $default;
21898 }
21899 }
21900 <?php
21901
21902
21903
21904
21905
21906
21907
21908
21909
21910
21911
21912 namespace Composer;
21913
21914 use Composer\Autoload\AutoloadGenerator;
21915 use Composer\DependencyResolver\DefaultPolicy;
21916 use Composer\DependencyResolver\Operation\UpdateOperation;
21917 use Composer\DependencyResolver\Operation\InstallOperation;
21918 use Composer\DependencyResolver\Operation\UninstallOperation;
21919 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
21920 use Composer\DependencyResolver\Operation\OperationInterface;
21921 use Composer\DependencyResolver\PolicyInterface;
21922 use Composer\DependencyResolver\Pool;
21923 use Composer\DependencyResolver\Request;
21924 use Composer\DependencyResolver\Rule;
21925 use Composer\DependencyResolver\Solver;
21926 use Composer\DependencyResolver\SolverProblemsException;
21927 use Composer\Downloader\DownloadManager;
21928 use Composer\EventDispatcher\EventDispatcher;
21929 use Composer\Installer\InstallationManager;
21930 use Composer\Installer\InstallerEvents;
21931 use Composer\Installer\NoopInstaller;
21932 use Composer\Installer\SuggestedPackagesReporter;
21933 use Composer\IO\IOInterface;
21934 use Composer\Package\AliasPackage;
21935 use Composer\Package\BasePackage;
21936 use Composer\Package\CompletePackage;
21937 use Composer\Package\CompletePackageInterface;
21938 use Composer\Package\Link;
21939 use Composer\Package\Loader\ArrayLoader;
21940 use Composer\Package\Dumper\ArrayDumper;
21941 use Composer\Semver\Constraint\Constraint;
21942 use Composer\Package\Locker;
21943 use Composer\Package\PackageInterface;
21944 use Composer\Package\RootPackageInterface;
21945 use Composer\Repository\CompositeRepository;
21946 use Composer\Repository\InstalledArrayRepository;
21947 use Composer\Repository\PlatformRepository;
21948 use Composer\Repository\RepositoryInterface;
21949 use Composer\Repository\RepositoryManager;
21950 use Composer\Repository\WritableRepositoryInterface;
21951 use Composer\Script\ScriptEvents;
21952
21953
21954
21955
21956
21957
21958
21959 class Installer
21960 {
21961
21962
21963
21964 protected $io;
21965
21966
21967
21968
21969 protected $config;
21970
21971
21972
21973
21974 protected $package;
21975
21976
21977
21978
21979 protected $downloadManager;
21980
21981
21982
21983
21984 protected $repositoryManager;
21985
21986
21987
21988
21989 protected $locker;
21990
21991
21992
21993
21994 protected $installationManager;
21995
21996
21997
21998
21999 protected $eventDispatcher;
22000
22001
22002
22003
22004 protected $autoloadGenerator;
22005
22006 protected $preferSource = false;
22007 protected $preferDist = false;
22008 protected $optimizeAutoloader = false;
22009 protected $classMapAuthoritative = false;
22010 protected $apcuAutoloader = false;
22011 protected $devMode = false;
22012 protected $dryRun = false;
22013 protected $verbose = false;
22014 protected $update = false;
22015 protected $dumpAutoloader = true;
22016 protected $runScripts = true;
22017 protected $ignorePlatformReqs = false;
22018 protected $preferStable = false;
22019 protected $preferLowest = false;
22020 protected $skipSuggest = false;
22021 protected $writeLock;
22022 protected $executeOperations = true;
22023
22024
22025
22026
22027
22028
22029 protected $updateWhitelist = null; 
22030 protected $whitelistDependencies = false; 
22031 protected $whitelistAllDependencies = false; 
22032
22033
22034
22035
22036 protected $suggestedPackagesReporter;
22037
22038
22039
22040
22041 protected $additionalInstalledRepository;
22042
22043
22044
22045
22046
22047
22048
22049
22050
22051
22052
22053
22054
22055
22056 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
22057 {
22058 $this->io = $io;
22059 $this->config = $config;
22060 $this->package = $package;
22061 $this->downloadManager = $downloadManager;
22062 $this->repositoryManager = $repositoryManager;
22063 $this->locker = $locker;
22064 $this->installationManager = $installationManager;
22065 $this->eventDispatcher = $eventDispatcher;
22066 $this->autoloadGenerator = $autoloadGenerator;
22067
22068 $this->writeLock = $config->get('lock');
22069 }
22070
22071
22072
22073
22074
22075
22076
22077 public function run()
22078 {
22079
22080
22081
22082
22083 gc_collect_cycles();
22084 gc_disable();
22085
22086
22087 if (!$this->update && !$this->locker->isLocked()) {
22088 $this->update = true;
22089 }
22090
22091 if ($this->dryRun) {
22092 $this->verbose = true;
22093 $this->runScripts = false;
22094 $this->executeOperations = false;
22095 $this->writeLock = false;
22096 $this->dumpAutoloader = false;
22097 $this->installationManager->addInstaller(new NoopInstaller);
22098 $this->mockLocalRepositories($this->repositoryManager);
22099 }
22100
22101 if ($this->runScripts) {
22102 $_SERVER['COMPOSER_DEV_MODE'] = $this->devMode ? '1' : '0';
22103 putenv('COMPOSER_DEV_MODE='.$_SERVER['COMPOSER_DEV_MODE']);
22104
22105
22106 $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
22107 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
22108 }
22109
22110 $this->downloadManager->setPreferSource($this->preferSource);
22111 $this->downloadManager->setPreferDist($this->preferDist);
22112
22113
22114 $localRepo = $this->repositoryManager->getLocalRepository();
22115 if ($this->update) {
22116 $platformOverrides = $this->config->get('platform') ?: array();
22117 } else {
22118 $platformOverrides = $this->locker->getPlatformOverrides();
22119 }
22120 $platformRepo = new PlatformRepository(array(), $platformOverrides);
22121 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
22122
22123 $aliases = $this->getRootAliases();
22124 $this->aliasPlatformPackages($platformRepo, $aliases);
22125
22126 if (!$this->suggestedPackagesReporter) {
22127 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
22128 }
22129
22130 try {
22131 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
22132 if ($res !== 0) {
22133 return $res;
22134 }
22135 } catch (\Exception $e) {
22136 if ($this->executeOperations && $this->config->get('notify-on-install')) {
22137 $this->installationManager->notifyInstalls($this->io);
22138 }
22139
22140 throw $e;
22141 }
22142 if ($this->executeOperations && $this->config->get('notify-on-install')) {
22143 $this->installationManager->notifyInstalls($this->io);
22144 }
22145
22146
22147 if ($this->devMode && !$this->skipSuggest) {
22148 $this->suggestedPackagesReporter->output($installedRepo);
22149 }
22150
22151
22152 foreach ($localRepo->getPackages() as $package) {
22153 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
22154 continue;
22155 }
22156
22157 $replacement = is_string($package->getReplacementPackage())
22158 ? 'Use ' . $package->getReplacementPackage() . ' instead'
22159 : 'No replacement was suggested';
22160
22161 $this->io->writeError(
22162 sprintf(
22163 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
22164 $package->getPrettyName(),
22165 $replacement
22166 )
22167 );
22168 }
22169
22170
22171 if ($this->update && $this->writeLock) {
22172 $localRepo->reload();
22173
22174 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
22175 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
22176
22177 $updatedLock = $this->locker->setLockData(
22178 array_diff($localRepo->getCanonicalPackages(), $devPackages),
22179 $devPackages,
22180 $platformReqs,
22181 $platformDevReqs,
22182 $aliases,
22183 $this->package->getMinimumStability(),
22184 $this->package->getStabilityFlags(),
22185 $this->preferStable || $this->package->getPreferStable(),
22186 $this->preferLowest,
22187 $this->config->get('platform') ?: array()
22188 );
22189 if ($updatedLock) {
22190 $this->io->writeError('<info>Writing lock file</info>');
22191 }
22192 }
22193
22194 if ($this->dumpAutoloader) {
22195
22196 if ($this->optimizeAutoloader) {
22197 $this->io->writeError('<info>Generating optimized autoload files</info>');
22198 } else {
22199 $this->io->writeError('<info>Generating autoload files</info>');
22200 }
22201
22202 $this->autoloadGenerator->setDevMode($this->devMode);
22203 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
22204 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
22205 $this->autoloadGenerator->setRunScripts($this->runScripts);
22206 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
22207 }
22208
22209 if ($this->executeOperations) {
22210
22211 foreach ($localRepo->getPackages() as $package) {
22212 $this->installationManager->ensureBinariesPresence($package);
22213 }
22214 }
22215
22216 $fundingCount = 0;
22217 foreach ($localRepo->getPackages() as $package) {
22218 if ($package instanceof CompletePackageInterface && !$package instanceof AliasPackage && $package->getFunding()) {
22219 $fundingCount++;
22220 }
22221 }
22222 if ($fundingCount) {
22223 $this->io->writeError(array(
22224 sprintf(
22225 "<info>%d package%s you are using %s looking for funding.</info>",
22226 $fundingCount,
22227 1 === $fundingCount ? '' : 's',
22228 1 === $fundingCount ? 'is' : 'are'
22229 ),
22230 '<info>Use the `composer fund` command to find out more!</info>',
22231 ));
22232 }
22233
22234 if ($this->runScripts) {
22235
22236 $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
22237 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
22238 }
22239
22240
22241 if (!defined('HHVM_VERSION')) {
22242 gc_enable();
22243 }
22244
22245 return 0;
22246 }
22247
22248
22249
22250
22251
22252
22253
22254
22255 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
22256 {
22257
22258 $lockedRepository = null;
22259 $repositories = null;
22260
22261
22262
22263
22264 if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
22265 try {
22266 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
22267 } catch (\RuntimeException $e) {
22268
22269 if ($this->package->getDevRequires()) {
22270 throw $e;
22271 }
22272
22273 $lockedRepository = $this->locker->getLockedRepository();
22274 }
22275 }
22276
22277 $this->allowListUpdateDependencies(
22278 $lockedRepository ?: $localRepo,
22279 $this->package->getRequires(),
22280 $this->package->getDevRequires()
22281 );
22282
22283 $this->io->writeError('<info>Loading composer repositories with package information</info>');
22284
22285
22286 $policy = $this->createPolicy();
22287 $pool = $this->createPool($this->update ? null : $lockedRepository);
22288 $pool->addRepository($installedRepo, $aliases);
22289 if ($this->update) {
22290 $repositories = $this->repositoryManager->getRepositories();
22291 foreach ($repositories as $repository) {
22292 $pool->addRepository($repository, $aliases);
22293 }
22294 }
22295
22296
22297
22298 if ($lockedRepository) {
22299 $pool->addRepository($lockedRepository, $aliases);
22300 }
22301
22302
22303 $request = $this->createRequest($this->package, $platformRepo);
22304
22305 if ($this->update) {
22306
22307 $removedUnstablePackages = array();
22308 foreach ($localRepo->getPackages() as $package) {
22309 if (
22310 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
22311 && $this->installationManager->isPackageInstalled($localRepo, $package)
22312 ) {
22313 $removedUnstablePackages[$package->getName()] = true;
22314 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
22315 }
22316 }
22317
22318 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
22319
22320 $request->updateAll();
22321
22322 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
22323
22324 foreach ($links as $link) {
22325 $request->install($link->getTarget(), $link->getConstraint());
22326 }
22327
22328
22329
22330 if ($this->updateWhitelist) {
22331 $currentPackages = $this->getCurrentPackages($installedRepo);
22332
22333
22334 $candidates = array();
22335 foreach ($links as $link) {
22336 $candidates[$link->getTarget()] = true;
22337 $rootRequires[$link->getTarget()] = $link;
22338 }
22339 foreach ($currentPackages as $package) {
22340 $candidates[$package->getName()] = true;
22341 }
22342
22343
22344 foreach ($candidates as $candidate => $dummy) {
22345 foreach ($currentPackages as $curPackage) {
22346 if ($curPackage->getName() === $candidate) {
22347 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
22348 $constraint = new Constraint('=', $curPackage->getVersion());
22349 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
22350 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
22351 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
22352 $request->install($curPackage->getName(), $constraint);
22353 }
22354 break;
22355 }
22356 }
22357 }
22358 }
22359 } else {
22360 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
22361
22362 if (!$this->locker->isFresh()) {
22363 $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. It is recommended that you run `composer update` or `composer update <package name>`.</warning>', true, IOInterface::QUIET);
22364 }
22365
22366 foreach ($lockedRepository->getPackages() as $package) {
22367 $version = $package->getVersion();
22368 if (isset($aliases[$package->getName()][$version])) {
22369 $version = $aliases[$package->getName()][$version]['alias_normalized'];
22370 }
22371 $constraint = new Constraint('=', $version);
22372 $constraint->setPrettyString($package->getPrettyVersion());
22373 $request->install($package->getName(), $constraint);
22374 }
22375
22376 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
22377 $request->install($link->getTarget(), $link->getConstraint());
22378 }
22379 }
22380
22381
22382 $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
22383
22384
22385 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
22386 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
22387 try {
22388 $operations = $solver->solve($request, $this->ignorePlatformReqs);
22389 $ruleSetSize = $solver->getRuleSetSize();
22390 $solver = null;
22391 } catch (SolverProblemsException $e) {
22392 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
22393 $this->io->writeError($e->getMessage());
22394 if ($this->update && !$this->devMode) {
22395 $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);
22396 }
22397
22398 return array(max(1, $e->getCode()), array());
22399 }
22400
22401
22402 $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
22403
22404 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
22405
22406 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
22407 $this->io->writeError("Analyzed ".$ruleSetSize." rules to resolve dependencies", true, IOInterface::VERBOSE);
22408
22409
22410 if (!$operations) {
22411 $this->io->writeError('Nothing to install or update');
22412 }
22413
22414 $operations = $this->movePluginsToFront($operations);
22415 $operations = $this->moveUninstallsToFront($operations);
22416
22417
22418
22419 if ($this->update) {
22420 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
22421 if (!$this->devMode) {
22422 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
22423 }
22424 } else {
22425 $devPackages = null;
22426 }
22427
22428 if ($operations) {
22429 $installs = $updates = $uninstalls = array();
22430 foreach ($operations as $operation) {
22431 if ($operation instanceof InstallOperation) {
22432 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
22433 } elseif ($operation instanceof UpdateOperation) {
22434 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
22435 } elseif ($operation instanceof UninstallOperation) {
22436 $uninstalls[] = $operation->getPackage()->getPrettyName();
22437 }
22438 }
22439
22440 $this->io->writeError(sprintf(
22441 "<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
22442 count($installs),
22443 1 === count($installs) ? '' : 's',
22444 count($updates),
22445 1 === count($updates) ? '' : 's',
22446 count($uninstalls),
22447 1 === count($uninstalls) ? '' : 's'
22448 ));
22449 if ($installs) {
22450 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
22451 }
22452 if ($updates) {
22453 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
22454 }
22455 if ($uninstalls) {
22456 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
22457 }
22458 }
22459
22460 foreach ($operations as $operation) {
22461
22462 $jobType = $operation->getJobType();
22463 if ('install' === $jobType) {
22464 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
22465 }
22466
22467
22468 if ($this->update) {
22469 $package = null;
22470 if ('update' === $jobType) {
22471 $package = $operation->getTargetPackage();
22472 } elseif ('install' === $jobType) {
22473 $package = $operation->getPackage();
22474 }
22475 if ($package && $package->isDev()) {
22476 $references = $this->package->getReferences();
22477 if (isset($references[$package->getName()])) {
22478 $this->updateInstallReferences($package, $references[$package->getName()]);
22479 }
22480 }
22481 if ('update' === $jobType) {
22482 $targetPackage = $operation->getTargetPackage();
22483 if ($targetPackage->isDev()) {
22484 $initialPackage = $operation->getInitialPackage();
22485 if ($targetPackage->getVersion() === $initialPackage->getVersion()
22486 && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference())
22487 && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference())
22488 ) {
22489 $this->io->writeError('  - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG);
22490 $this->io->writeError('', true, IOInterface::DEBUG);
22491
22492 continue;
22493 }
22494 }
22495 }
22496 }
22497
22498 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($jobType);
22499 if (defined($event) && $this->runScripts) {
22500 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
22501 }
22502
22503
22504 if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
22505 $this->io->writeError('  - ' . $operation);
22506 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
22507 $this->io->writeError('  - ' . $operation);
22508 }
22509
22510 $this->installationManager->execute($localRepo, $operation);
22511
22512
22513 if ($this->verbose && $this->io->isVeryVerbose() && in_array($jobType, array('install', 'update'))) {
22514 $reason = $operation->getReason();
22515 if ($reason instanceof Rule) {
22516 switch ($reason->getReason()) {
22517 case Rule::RULE_JOB_INSTALL:
22518 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
22519 $this->io->writeError('');
22520 break;
22521 case Rule::RULE_PACKAGE_REQUIRES:
22522 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
22523 $this->io->writeError('');
22524 break;
22525 }
22526 }
22527 }
22528
22529 if ($this->executeOperations || $this->writeLock) {
22530 $localRepo->write();
22531 }
22532
22533 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($jobType);
22534 if (defined($event) && $this->runScripts) {
22535 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
22536 }
22537 }
22538
22539 if ($this->executeOperations) {
22540
22541 $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
22542 $localRepo->write();
22543 }
22544
22545
22546 if ($operations) {
22547 $vendorDir = $this->config->get('vendor-dir');
22548 if (is_dir($vendorDir)) {
22549
22550
22551 @touch($vendorDir);
22552 }
22553 }
22554
22555 return array(0, $devPackages);
22556 }
22557
22558
22559
22560
22561
22562
22563
22564
22565
22566
22567
22568 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
22569 {
22570 if (!$this->package->getDevRequires()) {
22571 return array();
22572 }
22573
22574
22575 $tempLocalRepo = clone $localRepo;
22576 foreach ($operations as $operation) {
22577 switch ($operation->getJobType()) {
22578 case 'install':
22579 case 'markAliasInstalled':
22580 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
22581 $tempLocalRepo->addPackage(clone $operation->getPackage());
22582 }
22583 break;
22584
22585 case 'uninstall':
22586 case 'markAliasUninstalled':
22587 $tempLocalRepo->removePackage($operation->getPackage());
22588 break;
22589
22590 case 'update':
22591 $tempLocalRepo->removePackage($operation->getInitialPackage());
22592 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
22593 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
22594 }
22595 break;
22596
22597 default:
22598 throw new \LogicException('Unknown type: '.$operation->getJobType());
22599 }
22600 }
22601
22602
22603
22604
22605 $localRepo = new InstalledArrayRepository(array());
22606 $loader = new ArrayLoader(null, true);
22607 $dumper = new ArrayDumper();
22608 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
22609 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
22610 }
22611 unset($tempLocalRepo, $loader, $dumper);
22612
22613 $policy = $this->createPolicy();
22614 $pool = $this->createPool();
22615 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
22616 $pool->addRepository($installedRepo, $aliases);
22617
22618
22619 $request = $this->createRequest($this->package, $platformRepo);
22620 $request->updateAll();
22621 foreach ($this->package->getRequires() as $link) {
22622 $request->install($link->getTarget(), $link->getConstraint());
22623 }
22624
22625
22626 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
22627 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
22628 $ops = $solver->solve($request, $this->ignorePlatformReqs);
22629 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
22630
22631 $devPackages = array();
22632 foreach ($ops as $op) {
22633 if ($op->getJobType() === 'uninstall') {
22634 $devPackages[] = $op->getPackage();
22635 }
22636 }
22637
22638 return $devPackages;
22639 }
22640
22641
22642
22643
22644 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
22645 {
22646 $finalOps = array();
22647 $packagesToSkip = array();
22648 foreach ($devPackages as $pkg) {
22649 $packagesToSkip[$pkg->getName()] = true;
22650 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
22651 if ($installedDevPkg instanceof AliasPackage) {
22652 $finalOps[] = new MarkAliasUninstalledOperation($installedDevPkg, 'non-dev install removing it');
22653 $installedDevPkg = $installedDevPkg->getAliasOf();
22654 }
22655 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
22656 }
22657 }
22658
22659
22660 foreach ($operations as $op) {
22661 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
22662 if (isset($packagesToSkip[$package->getName()])) {
22663 continue;
22664 }
22665
22666 $finalOps[] = $op;
22667 }
22668
22669 return $finalOps;
22670 }
22671
22672
22673
22674
22675
22676
22677
22678
22679
22680
22681
22682
22683
22684
22685 private function movePluginsToFront(array $operations)
22686 {
22687 $pluginsNoDeps = array();
22688 $pluginsWithDeps = array();
22689 $pluginRequires = array();
22690
22691 foreach (array_reverse($operations, true) as $idx => $op) {
22692 if ($op instanceof InstallOperation) {
22693 $package = $op->getPackage();
22694 } elseif ($op instanceof UpdateOperation) {
22695 $package = $op->getTargetPackage();
22696 } else {
22697 continue;
22698 }
22699
22700
22701 $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
22702
22703
22704 if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
22705
22706 $requires = array_filter(array_keys($package->getRequires()), function ($req) {
22707 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
22708 });
22709
22710
22711 if ($isPlugin && !count($requires)) {
22712
22713 array_unshift($pluginsNoDeps, $op);
22714 } else {
22715
22716 $pluginRequires = array_merge($pluginRequires, $requires);
22717
22718 array_unshift($pluginsWithDeps, $op);
22719 }
22720
22721 unset($operations[$idx]);
22722 }
22723 }
22724
22725 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
22726 }
22727
22728
22729
22730
22731
22732
22733
22734
22735 private function moveUninstallsToFront(array $operations)
22736 {
22737 $uninstOps = array();
22738 foreach ($operations as $idx => $op) {
22739 if ($op instanceof UninstallOperation) {
22740 $uninstOps[] = $op;
22741 unset($operations[$idx]);
22742 }
22743 }
22744
22745 return array_merge($uninstOps, $operations);
22746 }
22747
22748
22749
22750
22751 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
22752 {
22753
22754
22755
22756 $installedRootPackage = clone $this->package;
22757 $installedRootPackage->setRequires(array());
22758 $installedRootPackage->setDevRequires(array());
22759
22760 $repos = array(
22761 $localRepo,
22762 new InstalledArrayRepository(array($installedRootPackage)),
22763 $platformRepo,
22764 );
22765 $installedRepo = new CompositeRepository($repos);
22766 if ($this->additionalInstalledRepository) {
22767 $installedRepo->addRepository($this->additionalInstalledRepository);
22768 }
22769
22770 return $installedRepo;
22771 }
22772
22773
22774
22775
22776
22777 private function createPool(RepositoryInterface $lockedRepository = null)
22778 {
22779 if ($this->update) {
22780 $minimumStability = $this->package->getMinimumStability();
22781 $stabilityFlags = $this->package->getStabilityFlags();
22782
22783 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
22784 } else {
22785 $minimumStability = $this->locker->getMinimumStability();
22786 $stabilityFlags = $this->locker->getStabilityFlags();
22787
22788 $requires = array();
22789 foreach ($lockedRepository->getPackages() as $package) {
22790 $constraint = new Constraint('=', $package->getVersion());
22791 $constraint->setPrettyString($package->getPrettyVersion());
22792 $requires[$package->getName()] = $constraint;
22793 }
22794 }
22795
22796 $rootConstraints = array();
22797 foreach ($requires as $req => $constraint) {
22798
22799 if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
22800 continue;
22801 }
22802 if ($constraint instanceof Link) {
22803 $rootConstraints[$req] = $constraint->getConstraint();
22804 } else {
22805 $rootConstraints[$req] = $constraint;
22806 }
22807 }
22808
22809 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
22810 }
22811
22812
22813
22814
22815 private function createPolicy()
22816 {
22817 $preferStable = null;
22818 $preferLowest = null;
22819 if (!$this->update) {
22820 $preferStable = $this->locker->getPreferStable();
22821 $preferLowest = $this->locker->getPreferLowest();
22822 }
22823
22824
22825 if (null === $preferStable) {
22826 $preferStable = $this->preferStable || $this->package->getPreferStable();
22827 }
22828 if (null === $preferLowest) {
22829 $preferLowest = $this->preferLowest;
22830 }
22831
22832 return new DefaultPolicy($preferStable, $preferLowest);
22833 }
22834
22835
22836
22837
22838
22839
22840 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
22841 {
22842 $request = new Request();
22843
22844 $constraint = new Constraint('=', $rootPackage->getVersion());
22845 $constraint->setPrettyString($rootPackage->getPrettyVersion());
22846 $request->install($rootPackage->getName(), $constraint);
22847
22848 $fixedPackages = $platformRepo->getPackages();
22849 if ($this->additionalInstalledRepository) {
22850 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
22851 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
22852 }
22853
22854
22855
22856 $provided = $rootPackage->getProvides();
22857 foreach ($fixedPackages as $package) {
22858 $constraint = new Constraint('=', $package->getVersion());
22859 $constraint->setPrettyString($package->getPrettyVersion());
22860
22861
22862 if ($package->getRepository() !== $platformRepo
22863 || !isset($provided[$package->getName()])
22864 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
22865 ) {
22866 $request->fix($package->getName(), $constraint);
22867 }
22868 }
22869
22870 return $request;
22871 }
22872
22873
22874
22875
22876
22877
22878
22879
22880
22881
22882
22883
22884 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
22885 {
22886 if ($task === 'force-updates' && null === $operations) {
22887 throw new \InvalidArgumentException('Missing operations argument');
22888 }
22889 if ($task === 'force-links') {
22890 $operations = array();
22891 }
22892
22893 if ($this->update && $this->updateWhitelist) {
22894 $currentPackages = $this->getCurrentPackages($installedRepo);
22895 }
22896
22897 foreach ($localRepo->getCanonicalPackages() as $package) {
22898
22899 if (!$package->isDev()) {
22900 continue;
22901 }
22902
22903
22904 foreach ($operations as $operation) {
22905 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
22906 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
22907 ) {
22908 continue 2;
22909 }
22910 }
22911
22912 if ($this->update) {
22913
22914 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
22915
22916 foreach ($currentPackages as $curPackage) {
22917 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
22918 if ($task === 'force-links') {
22919 $package->setRequires($curPackage->getRequires());
22920 $package->setConflicts($curPackage->getConflicts());
22921 $package->setProvides($curPackage->getProvides());
22922 $package->setReplaces($curPackage->getReplaces());
22923 } elseif ($task === 'force-updates') {
22924 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
22925 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
22926 ) {
22927 $operations[] = new UpdateOperation($package, $curPackage);
22928 }
22929 }
22930
22931 break;
22932 }
22933 }
22934
22935 continue;
22936 }
22937
22938
22939 $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
22940 foreach ($matches as $index => $match) {
22941
22942 if (!in_array($match->getRepository(), $repositories, true)) {
22943 unset($matches[$index]);
22944 continue;
22945 }
22946
22947
22948 if ($match->getName() !== $package->getName()) {
22949 unset($matches[$index]);
22950 continue;
22951 }
22952
22953 $matches[$index] = $match->getId();
22954 }
22955
22956
22957 if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
22958 $newPackage = $pool->literalToPackage($matches[0]);
22959
22960 if ($task === 'force-links' && $newPackage) {
22961 $package->setRequires($newPackage->getRequires());
22962 $package->setConflicts($newPackage->getConflicts());
22963 $package->setProvides($newPackage->getProvides());
22964 $package->setReplaces($newPackage->getReplaces());
22965 }
22966
22967 if (
22968 $task === 'force-updates'
22969 && $newPackage
22970 && (
22971 ($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
22972 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
22973 )
22974 ) {
22975 $operations[] = new UpdateOperation($package, $newPackage);
22976
22977 continue;
22978 }
22979 }
22980
22981 if ($task === 'force-updates') {
22982
22983 $references = $this->package->getReferences();
22984
22985 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
22986
22987 $operations[] = new UpdateOperation($package, clone $package);
22988 }
22989 }
22990 } else {
22991
22992 foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
22993 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
22994 if ($task === 'force-links') {
22995 $package->setRequires($lockedPackage->getRequires());
22996 $package->setConflicts($lockedPackage->getConflicts());
22997 $package->setProvides($lockedPackage->getProvides());
22998 $package->setReplaces($lockedPackage->getReplaces());
22999 } elseif ($task === 'force-updates') {
23000 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
23001 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
23002 ) {
23003 $operations[] = new UpdateOperation($package, $lockedPackage);
23004 }
23005 }
23006
23007 break;
23008 }
23009 }
23010 }
23011 }
23012
23013 return $operations;
23014 }
23015
23016
23017
23018
23019
23020
23021 private function getCurrentPackages($installedRepo)
23022 {
23023 if ($this->locker->isLocked()) {
23024 try {
23025 return $this->locker->getLockedRepository(true)->getPackages();
23026 } catch (\RuntimeException $e) {
23027
23028 return $this->locker->getLockedRepository()->getPackages();
23029 }
23030 }
23031
23032 return $installedRepo->getPackages();
23033 }
23034
23035
23036
23037
23038 private function getRootAliases()
23039 {
23040 if ($this->update) {
23041 $aliases = $this->package->getAliases();
23042 } else {
23043 $aliases = $this->locker->getAliases();
23044 }
23045
23046 $normalizedAliases = array();
23047
23048 foreach ($aliases as $alias) {
23049 $normalizedAliases[$alias['package']][$alias['version']] = array(
23050 'alias' => $alias['alias'],
23051 'alias_normalized' => $alias['alias_normalized'],
23052 );
23053 }
23054
23055 return $normalizedAliases;
23056 }
23057
23058
23059
23060
23061
23062
23063
23064 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
23065 {
23066 if (!$this->update) {
23067 return;
23068 }
23069
23070 $rootRefs = $this->package->getReferences();
23071
23072 foreach ($localRepo->getCanonicalPackages() as $package) {
23073
23074 $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
23075 foreach ($matches as $index => $match) {
23076
23077 if (!in_array($match->getRepository(), $repositories, true)) {
23078 unset($matches[$index]);
23079 continue;
23080 }
23081
23082
23083 if ($match->getName() !== $package->getName()) {
23084 unset($matches[$index]);
23085 continue;
23086 }
23087
23088 $matches[$index] = $match->getId();
23089 }
23090
23091
23092 if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
23093 $newPackage = $pool->literalToPackage($matches[0]);
23094
23095
23096 $sourceUrl = $package->getSourceUrl();
23097 $newSourceUrl = $newPackage->getSourceUrl();
23098 $newReference = $newPackage->getSourceReference();
23099
23100 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
23101 $newReference = $rootRefs[$package->getName()];
23102 }
23103
23104 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl(), $newPackage->getDistType(), $newPackage->getDistSha1Checksum());
23105
23106 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
23107 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
23108 }
23109
23110 $package->setDistMirrors($newPackage->getDistMirrors());
23111 $package->setSourceMirrors($newPackage->getSourceMirrors());
23112 $package->setTransportOptions($newPackage->getTransportOptions());
23113 }
23114 }
23115 }
23116
23117 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl, $distType, $distShaSum)
23118 {
23119 $oldSourceRef = $package->getSourceReference();
23120
23121 if ($package->getSourceUrl() !== $sourceUrl) {
23122 $package->setSourceType($sourceType);
23123 $package->setSourceUrl($sourceUrl);
23124 $package->setSourceReference($sourceReference);
23125 }
23126
23127
23128
23129 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $distUrl)) {
23130 $package->setDistUrl($distUrl);
23131 $package->setDistType($distType);
23132 $package->setDistSha1Checksum($distShaSum);
23133 $this->updateInstallReferences($package, $sourceReference);
23134 }
23135
23136 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
23137 $this->updateInstallReferences($package, $oldSourceRef);
23138 }
23139 }
23140
23141 private function updateInstallReferences(PackageInterface $package, $reference)
23142 {
23143 if (!$reference) {
23144 return;
23145 }
23146
23147 $package->setSourceReference($reference);
23148
23149 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $package->getDistUrl())) {
23150 $package->setDistReference($reference);
23151 $package->setDistUrl(preg_replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
23152 } elseif ($package->getDistReference()) { 
23153 $package->setDistReference($reference);
23154 }
23155 }
23156
23157
23158
23159
23160
23161 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
23162 {
23163 foreach ($aliases as $package => $versions) {
23164 foreach ($versions as $version => $alias) {
23165 $packages = $platformRepo->findPackages($package, $version);
23166 foreach ($packages as $package) {
23167 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
23168 $aliasPackage->setRootPackageAlias(true);
23169 $platformRepo->addPackage($aliasPackage);
23170 }
23171 }
23172 }
23173 }
23174
23175
23176
23177
23178
23179 private function isUpdateable(PackageInterface $package)
23180 {
23181 if (!$this->updateWhitelist) {
23182 throw new \LogicException('isUpdateable should only be called when an allow list is present');
23183 }
23184
23185 foreach ($this->updateWhitelist as $pattern => $void) {
23186 $patternRegexp = BasePackage::packageNameToRegexp($pattern);
23187 if (preg_match($patternRegexp, $package->getName())) {
23188 return true;
23189 }
23190 }
23191
23192 return false;
23193 }
23194
23195
23196
23197
23198
23199 private function extractPlatformRequirements($links)
23200 {
23201 $platformReqs = array();
23202 foreach ($links as $link) {
23203 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
23204 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
23205 }
23206 }
23207
23208 return $platformReqs;
23209 }
23210
23211
23212
23213
23214
23215
23216
23217
23218
23219
23220
23221
23222
23223
23224 private function allowListUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
23225 {
23226 if (!$this->updateWhitelist) {
23227 return;
23228 }
23229
23230 $rootRequires = array_merge($rootRequires, $rootDevRequires);
23231
23232 $skipPackages = array();
23233 if (!$this->whitelistAllDependencies) {
23234 foreach ($rootRequires as $require) {
23235 $skipPackages[$require->getTarget()] = true;
23236 }
23237 }
23238
23239 $pool = new Pool('dev');
23240 $pool->addRepository($localOrLockRepo);
23241
23242 $seen = array();
23243
23244 $rootRequiredPackageNames = array_keys($rootRequires);
23245
23246 foreach ($this->updateWhitelist as $packageName => $void) {
23247 $packageQueue = new \SplQueue;
23248 $nameMatchesRequiredPackage = false;
23249
23250 $depPackages = $pool->whatProvides($packageName);
23251 $matchesByPattern = array();
23252
23253 if (empty($depPackages)) {
23254
23255 $allowListPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$');
23256 foreach ($localOrLockRepo->search($allowListPatternSearchRegexp) as $installedPackage) {
23257 $matchesByPattern[] = $pool->whatProvides($installedPackage['name']);
23258 }
23259
23260
23261 $allowListPatternRegexp = BasePackage::packageNameToRegexp($packageName);
23262 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
23263 if (preg_match($allowListPatternRegexp, $rootRequiredPackageName)) {
23264 $nameMatchesRequiredPackage = true;
23265 break;
23266 }
23267 }
23268 }
23269
23270 if (!empty($matchesByPattern)) {
23271 $depPackages = array_merge($depPackages, call_user_func_array('array_merge', $matchesByPattern));
23272 }
23273
23274 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
23275 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
23276 }
23277
23278 foreach ($depPackages as $depPackage) {
23279 $packageQueue->enqueue($depPackage);
23280 }
23281
23282 while (!$packageQueue->isEmpty()) {
23283 $package = $packageQueue->dequeue();
23284 if (isset($seen[$package->getId()])) {
23285 continue;
23286 }
23287
23288 $seen[$package->getId()] = true;
23289 $this->updateWhitelist[$package->getName()] = true;
23290
23291 if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) {
23292 continue;
23293 }
23294
23295 $requires = $package->getRequires();
23296
23297 foreach ($requires as $require) {
23298 $requirePackages = $pool->whatProvides($require->getTarget());
23299
23300 foreach ($requirePackages as $requirePackage) {
23301 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
23302 continue;
23303 }
23304
23305 if (isset($skipPackages[$requirePackage->getName()]) && !preg_match(BasePackage::packageNameToRegexp($packageName), $requirePackage->getName())) {
23306 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly allowed. Ignoring.</warning>');
23307 continue;
23308 }
23309
23310 $packageQueue->enqueue($requirePackage);
23311 }
23312 }
23313 }
23314 }
23315 }
23316
23317
23318
23319
23320
23321
23322
23323
23324 private function mockLocalRepositories(RepositoryManager $rm)
23325 {
23326 $packages = array();
23327 foreach ($rm->getLocalRepository()->getPackages() as $package) {
23328 $packages[(string) $package] = clone $package;
23329 }
23330 foreach ($packages as $key => $package) {
23331 if ($package instanceof AliasPackage) {
23332 $alias = (string) $package->getAliasOf();
23333 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
23334 }
23335 }
23336 $rm->setLocalRepository(
23337 new InstalledArrayRepository($packages)
23338 );
23339 }
23340
23341
23342
23343
23344
23345
23346
23347
23348 public static function create(IOInterface $io, Composer $composer)
23349 {
23350 return new static(
23351 $io,
23352 $composer->getConfig(),
23353 $composer->getPackage(),
23354 $composer->getDownloadManager(),
23355 $composer->getRepositoryManager(),
23356 $composer->getLocker(),
23357 $composer->getInstallationManager(),
23358 $composer->getEventDispatcher(),
23359 $composer->getAutoloadGenerator()
23360 );
23361 }
23362
23363
23364
23365
23366
23367 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
23368 {
23369 $this->additionalInstalledRepository = $additionalInstalledRepository;
23370
23371 return $this;
23372 }
23373
23374
23375
23376
23377
23378
23379
23380 public function setDryRun($dryRun = true)
23381 {
23382 $this->dryRun = (bool) $dryRun;
23383
23384 return $this;
23385 }
23386
23387
23388
23389
23390
23391
23392 public function isDryRun()
23393 {
23394 return $this->dryRun;
23395 }
23396
23397
23398
23399
23400
23401
23402
23403 public function setPreferSource($preferSource = true)
23404 {
23405 $this->preferSource = (bool) $preferSource;
23406
23407 return $this;
23408 }
23409
23410
23411
23412
23413
23414
23415
23416 public function setPreferDist($preferDist = true)
23417 {
23418 $this->preferDist = (bool) $preferDist;
23419
23420 return $this;
23421 }
23422
23423
23424
23425
23426
23427
23428
23429 public function setOptimizeAutoloader($optimizeAutoloader = false)
23430 {
23431 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
23432 if (!$this->optimizeAutoloader) {
23433
23434
23435 $this->setClassMapAuthoritative(false);
23436 }
23437
23438 return $this;
23439 }
23440
23441
23442
23443
23444
23445
23446
23447
23448 public function setClassMapAuthoritative($classMapAuthoritative = false)
23449 {
23450 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
23451 if ($this->classMapAuthoritative) {
23452
23453 $this->setOptimizeAutoloader(true);
23454 }
23455
23456 return $this;
23457 }
23458
23459
23460
23461
23462
23463
23464
23465 public function setApcuAutoloader($apcuAutoloader = false)
23466 {
23467 $this->apcuAutoloader = (bool) $apcuAutoloader;
23468
23469 return $this;
23470 }
23471
23472
23473
23474
23475
23476
23477
23478 public function setUpdate($update = true)
23479 {
23480 $this->update = (bool) $update;
23481
23482 return $this;
23483 }
23484
23485
23486
23487
23488
23489
23490
23491 public function setDevMode($devMode = true)
23492 {
23493 $this->devMode = (bool) $devMode;
23494
23495 return $this;
23496 }
23497
23498
23499
23500
23501
23502
23503
23504
23505
23506 public function setDumpAutoloader($dumpAutoloader = true)
23507 {
23508 $this->dumpAutoloader = (bool) $dumpAutoloader;
23509
23510 return $this;
23511 }
23512
23513
23514
23515
23516
23517
23518
23519
23520
23521 public function setRunScripts($runScripts = true)
23522 {
23523 $this->runScripts = (bool) $runScripts;
23524
23525 return $this;
23526 }
23527
23528
23529
23530
23531
23532
23533
23534 public function setConfig(Config $config)
23535 {
23536 $this->config = $config;
23537
23538 return $this;
23539 }
23540
23541
23542
23543
23544
23545
23546
23547 public function setVerbose($verbose = true)
23548 {
23549 $this->verbose = (bool) $verbose;
23550
23551 return $this;
23552 }
23553
23554
23555
23556
23557
23558
23559 public function isVerbose()
23560 {
23561 return $this->verbose;
23562 }
23563
23564
23565
23566
23567
23568
23569
23570 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
23571 {
23572 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
23573
23574 return $this;
23575 }
23576
23577
23578
23579
23580
23581
23582
23583
23584
23585
23586 public function setUpdateWhitelist(array $packages)
23587 {
23588 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
23589
23590 return $this;
23591 }
23592
23593
23594
23595
23596
23597
23598
23599
23600 public function setUpdateAllowList(array $packages)
23601 {
23602
23603 return $this->setUpdateWhitelist($packages);
23604 }
23605
23606
23607
23608
23609 public function setWhitelistDependencies($updateDependencies = true)
23610 {
23611 return $this->setWhitelistTransitiveDependencies($updateDependencies);
23612 }
23613
23614
23615
23616
23617
23618
23619
23620
23621
23622
23623
23624
23625 public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true)
23626 {
23627 $this->whitelistDependencies = (bool) $updateTransitiveDependencies;
23628
23629 return $this;
23630 }
23631
23632
23633
23634
23635
23636
23637
23638
23639
23640
23641 public function setAllowListTransitiveDependencies($updateTransitiveDependencies = true)
23642 {
23643
23644 return $this->setWhitelistTransitiveDependencies($updateTransitiveDependencies);
23645 }
23646
23647
23648
23649
23650
23651
23652
23653
23654
23655
23656
23657
23658 public function setWhitelistAllDependencies($updateAllDependencies = true)
23659 {
23660 $this->whitelistAllDependencies = (bool) $updateAllDependencies;
23661
23662 return $this;
23663 }
23664
23665
23666
23667
23668
23669
23670
23671
23672
23673
23674 public function setAllowListAllDependencies($updateAllDependencies = true)
23675 {
23676
23677 return $this->setWhitelistAllDependencies($updateAllDependencies);
23678 }
23679
23680
23681
23682
23683
23684
23685
23686 public function setPreferStable($preferStable = true)
23687 {
23688 $this->preferStable = (bool) $preferStable;
23689
23690 return $this;
23691 }
23692
23693
23694
23695
23696
23697
23698
23699 public function setPreferLowest($preferLowest = true)
23700 {
23701 $this->preferLowest = (bool) $preferLowest;
23702
23703 return $this;
23704 }
23705
23706
23707
23708
23709
23710
23711
23712
23713
23714 public function setWriteLock($writeLock = true)
23715 {
23716 $this->writeLock = (bool) $writeLock;
23717
23718 return $this;
23719 }
23720
23721
23722
23723
23724
23725
23726
23727
23728
23729 public function setExecuteOperations($executeOperations = true)
23730 {
23731 $this->executeOperations = (bool) $executeOperations;
23732
23733 return $this;
23734 }
23735
23736
23737
23738
23739
23740
23741
23742 public function setSkipSuggest($skipSuggest = true)
23743 {
23744 $this->skipSuggest = (bool) $skipSuggest;
23745
23746 return $this;
23747 }
23748
23749
23750
23751
23752
23753
23754
23755
23756
23757
23758 public function disablePlugins()
23759 {
23760 $this->installationManager->disablePlugins();
23761
23762 return $this;
23763 }
23764
23765
23766
23767
23768
23769 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
23770 {
23771 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
23772
23773 return $this;
23774 }
23775 }
23776 <?php
23777
23778
23779
23780
23781
23782
23783
23784
23785
23786
23787
23788 namespace Composer\Installer;
23789
23790 use Composer\IO\IOInterface;
23791 use Composer\Package\PackageInterface;
23792 use Composer\Util\Filesystem;
23793 use Composer\Util\Platform;
23794 use Composer\Util\ProcessExecutor;
23795 use Composer\Util\Silencer;
23796
23797
23798
23799
23800
23801
23802
23803
23804 class BinaryInstaller
23805 {
23806 protected $binDir;
23807 protected $binCompat;
23808 protected $io;
23809 protected $filesystem;
23810
23811
23812
23813
23814
23815
23816
23817 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
23818 {
23819 $this->binDir = $binDir;
23820 $this->binCompat = $binCompat;
23821 $this->io = $io;
23822 $this->filesystem = $filesystem ?: new Filesystem();
23823 }
23824
23825 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
23826 {
23827 $binaries = $this->getBinaries($package);
23828 if (!$binaries) {
23829 return;
23830 }
23831 foreach ($binaries as $bin) {
23832 $binPath = $installPath.'/'.$bin;
23833 if (!file_exists($binPath)) {
23834 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
23835 continue;
23836 }
23837
23838
23839
23840
23841
23842 $binPath = realpath($binPath);
23843
23844 $this->initializeBinDir();
23845 $link = $this->binDir.'/'.basename($bin);
23846 if (file_exists($link)) {
23847 if (is_link($link)) {
23848
23849
23850
23851 Silencer::call('chmod', $link, 0777 & ~umask());
23852 }
23853 if ($warnOnOverwrite) {
23854 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
23855 }
23856 continue;
23857 }
23858
23859 if ($this->binCompat === "auto") {
23860 if (Platform::isWindows()) {
23861 $this->installFullBinaries($binPath, $link, $bin, $package);
23862 } else {
23863 $this->installSymlinkBinaries($binPath, $link);
23864 }
23865 } elseif ($this->binCompat === "full") {
23866 $this->installFullBinaries($binPath, $link, $bin, $package);
23867 }
23868 Silencer::call('chmod', $link, 0777 & ~umask());
23869 }
23870 }
23871
23872 public function removeBinaries(PackageInterface $package)
23873 {
23874 $this->initializeBinDir();
23875
23876 $binaries = $this->getBinaries($package);
23877 if (!$binaries) {
23878 return;
23879 }
23880 foreach ($binaries as $bin) {
23881 $link = $this->binDir.'/'.basename($bin);
23882 if (is_link($link) || file_exists($link)) {
23883 $this->filesystem->unlink($link);
23884 }
23885 if (file_exists($link.'.bat')) {
23886 $this->filesystem->unlink($link.'.bat');
23887 }
23888 }
23889
23890
23891 if (is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) {
23892 Silencer::call('rmdir', $this->binDir);
23893 }
23894 }
23895
23896 public static function determineBinaryCaller($bin)
23897 {
23898 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
23899 return 'call';
23900 }
23901
23902 $handle = fopen($bin, 'r');
23903 $line = fgets($handle);
23904 fclose($handle);
23905 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
23906 return trim($match[1]);
23907 }
23908
23909 return 'php';
23910 }
23911
23912 protected function getBinaries(PackageInterface $package)
23913 {
23914 return $package->getBinaries();
23915 }
23916
23917 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
23918 {
23919
23920 if ('.bat' !== substr($binPath, -4)) {
23921 $this->installUnixyProxyBinaries($binPath, $link);
23922 @chmod($link, 0777 & ~umask());
23923 $link .= '.bat';
23924 if (file_exists($link)) {
23925 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
23926 }
23927 }
23928 if (!file_exists($link)) {
23929 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
23930 }
23931 }
23932
23933 protected function installSymlinkBinaries($binPath, $link)
23934 {
23935 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
23936 $this->installUnixyProxyBinaries($binPath, $link);
23937 }
23938 }
23939
23940 protected function installUnixyProxyBinaries($binPath, $link)
23941 {
23942 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
23943 }
23944
23945 protected function initializeBinDir()
23946 {
23947 $this->filesystem->ensureDirectoryExists($this->binDir);
23948 $this->binDir = realpath($this->binDir);
23949 }
23950
23951 protected function generateWindowsProxyCode($bin, $link)
23952 {
23953 $binPath = $this->filesystem->findShortestPath($link, $bin);
23954 $caller = self::determineBinaryCaller($bin);
23955
23956 return "@ECHO OFF\r\n".
23957 "setlocal DISABLEDELAYEDEXPANSION\r\n".
23958 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
23959 "{$caller} \"%BIN_TARGET%\" %*\r\n";
23960 }
23961
23962 protected function generateUnixyProxyCode($bin, $link)
23963 {
23964 $binPath = $this->filesystem->findShortestPath($link, $bin);
23965
23966 $binDir = ProcessExecutor::escape(dirname($binPath));
23967 $binFile = basename($binPath);
23968
23969 $proxyCode = <<<PROXY
23970 #!/usr/bin/env sh
23971
23972 dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
23973
23974 if [ -d /proc/cygdrive ]; then
23975     case \$(which php) in
23976         \$(readlink -n /proc/cygdrive)/*)
23977             # We are in Cygwin using Windows php, so the path must be translated
23978             dir=\$(cygpath -m "\$dir");
23979             ;;
23980     esac
23981 fi
23982
23983 "\${dir}/$binFile" "\$@"
23984
23985 PROXY;
23986
23987 return $proxyCode;
23988 }
23989 }
23990 <?php
23991
23992
23993
23994
23995
23996
23997
23998
23999
24000
24001
24002 namespace Composer\Installer;
24003
24004 use Composer\Package\PackageInterface;
24005
24006
24007
24008
24009
24010
24011 interface BinaryPresenceInterface
24012 {
24013
24014
24015
24016
24017
24018 public function ensureBinariesPresence(PackageInterface $package);
24019 }
24020 <?php
24021
24022
24023
24024
24025
24026
24027
24028
24029
24030
24031
24032 namespace Composer\Installer;
24033
24034 use Composer\IO\IOInterface;
24035 use Composer\Package\PackageInterface;
24036 use Composer\Package\AliasPackage;
24037 use Composer\Repository\RepositoryInterface;
24038 use Composer\Repository\InstalledRepositoryInterface;
24039 use Composer\DependencyResolver\Operation\OperationInterface;
24040 use Composer\DependencyResolver\Operation\InstallOperation;
24041 use Composer\DependencyResolver\Operation\UpdateOperation;
24042 use Composer\DependencyResolver\Operation\UninstallOperation;
24043 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
24044 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
24045 use Composer\Util\StreamContextFactory;
24046
24047
24048
24049
24050
24051
24052
24053
24054 class InstallationManager
24055 {
24056 private $installers = array();
24057 private $cache = array();
24058 private $notifiablePackages = array();
24059
24060 public function reset()
24061 {
24062 $this->notifiablePackages = array();
24063 }
24064
24065
24066
24067
24068
24069
24070 public function addInstaller(InstallerInterface $installer)
24071 {
24072 array_unshift($this->installers, $installer);
24073 $this->cache = array();
24074 }
24075
24076
24077
24078
24079
24080
24081 public function removeInstaller(InstallerInterface $installer)
24082 {
24083 if (false !== ($key = array_search($installer, $this->installers, true))) {
24084 array_splice($this->installers, $key, 1);
24085 $this->cache = array();
24086 }
24087 }
24088
24089
24090
24091
24092
24093
24094
24095
24096 public function disablePlugins()
24097 {
24098 foreach ($this->installers as $i => $installer) {
24099 if (!$installer instanceof PluginInstaller) {
24100 continue;
24101 }
24102
24103 unset($this->installers[$i]);
24104 }
24105 }
24106
24107
24108
24109
24110
24111
24112
24113
24114
24115 public function getInstaller($type)
24116 {
24117 $type = strtolower($type);
24118
24119 if (isset($this->cache[$type])) {
24120 return $this->cache[$type];
24121 }
24122
24123 foreach ($this->installers as $installer) {
24124 if ($installer->supports($type)) {
24125 return $this->cache[$type] = $installer;
24126 }
24127 }
24128
24129 throw new \InvalidArgumentException('Unknown installer type: '.$type);
24130 }
24131
24132
24133
24134
24135
24136
24137
24138
24139
24140 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24141 {
24142 if ($package instanceof AliasPackage) {
24143 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
24144 }
24145
24146 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
24147 }
24148
24149
24150
24151
24152
24153
24154
24155 public function ensureBinariesPresence(PackageInterface $package)
24156 {
24157 try {
24158 $installer = $this->getInstaller($package->getType());
24159 } catch (\InvalidArgumentException $e) {
24160
24161 return;
24162 }
24163
24164
24165 if ($installer instanceof BinaryPresenceInterface) {
24166 $installer->ensureBinariesPresence($package);
24167 }
24168 }
24169
24170
24171
24172
24173
24174
24175
24176 public function execute(RepositoryInterface $repo, OperationInterface $operation)
24177 {
24178 $method = $operation->getJobType();
24179 $this->$method($repo, $operation);
24180 }
24181
24182
24183
24184
24185
24186
24187
24188 public function install(RepositoryInterface $repo, InstallOperation $operation)
24189 {
24190 $package = $operation->getPackage();
24191 $installer = $this->getInstaller($package->getType());
24192 $installer->install($repo, $package);
24193 $this->markForNotification($package);
24194 }
24195
24196
24197
24198
24199
24200
24201
24202 public function update(RepositoryInterface $repo, UpdateOperation $operation)
24203 {
24204 $initial = $operation->getInitialPackage();
24205 $target = $operation->getTargetPackage();
24206
24207 $initialType = $initial->getType();
24208 $targetType = $target->getType();
24209
24210 if ($initialType === $targetType) {
24211 $installer = $this->getInstaller($initialType);
24212 $installer->update($repo, $initial, $target);
24213 $this->markForNotification($target);
24214 } else {
24215 $this->getInstaller($initialType)->uninstall($repo, $initial);
24216 $this->getInstaller($targetType)->install($repo, $target);
24217 }
24218 }
24219
24220
24221
24222
24223
24224
24225
24226 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
24227 {
24228 $package = $operation->getPackage();
24229 $installer = $this->getInstaller($package->getType());
24230 $installer->uninstall($repo, $package);
24231 }
24232
24233
24234
24235
24236
24237
24238
24239 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
24240 {
24241 $package = $operation->getPackage();
24242
24243 if (!$repo->hasPackage($package)) {
24244 $repo->addPackage(clone $package);
24245 }
24246 }
24247
24248
24249
24250
24251
24252
24253
24254 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
24255 {
24256 $package = $operation->getPackage();
24257
24258 $repo->removePackage($package);
24259 }
24260
24261
24262
24263
24264
24265
24266
24267 public function getInstallPath(PackageInterface $package)
24268 {
24269 $installer = $this->getInstaller($package->getType());
24270
24271 return $installer->getInstallPath($package);
24272 }
24273
24274 public function notifyInstalls(IOInterface $io)
24275 {
24276 foreach ($this->notifiablePackages as $repoUrl => $packages) {
24277 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
24278 if ($io->hasAuthentication($repositoryName)) {
24279 $auth = $io->getAuthentication($repositoryName);
24280 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
24281 $authHeader = 'Authorization: Basic '.$authStr;
24282 }
24283
24284
24285 if (strpos($repoUrl, '%package%')) {
24286 foreach ($packages as $package) {
24287 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
24288
24289 $params = array(
24290 'version' => $package->getPrettyVersion(),
24291 'version_normalized' => $package->getVersion(),
24292 );
24293 $opts = array('http' =>
24294 array(
24295 'method' => 'POST',
24296 'header' => array('Content-type: application/x-www-form-urlencoded'),
24297 'content' => http_build_query($params, '', '&'),
24298 'timeout' => 3,
24299 ),
24300 );
24301 if (isset($authHeader)) {
24302 $opts['http']['header'][] = $authHeader;
24303 }
24304
24305 $context = StreamContextFactory::getContext($url, $opts);
24306 @file_get_contents($url, false, $context);
24307 }
24308
24309 continue;
24310 }
24311
24312 $postData = array('downloads' => array());
24313 foreach ($packages as $package) {
24314 $postData['downloads'][] = array(
24315 'name' => $package->getPrettyName(),
24316 'version' => $package->getVersion(),
24317 );
24318 }
24319
24320 $opts = array('http' =>
24321 array(
24322 'method' => 'POST',
24323 'header' => array('Content-Type: application/json'),
24324 'content' => json_encode($postData),
24325 'timeout' => 6,
24326 ),
24327 );
24328 if (isset($authHeader)) {
24329 $opts['http']['header'][] = $authHeader;
24330 }
24331
24332 $context = StreamContextFactory::getContext($repoUrl, $opts);
24333 @file_get_contents($repoUrl, false, $context);
24334 }
24335
24336 $this->reset();
24337 }
24338
24339 private function markForNotification(PackageInterface $package)
24340 {
24341 if ($package->getNotificationUrl()) {
24342 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
24343 }
24344 }
24345 }
24346 <?php
24347
24348
24349
24350
24351
24352
24353
24354
24355
24356
24357
24358 namespace Composer\Installer;
24359
24360 use Composer\Composer;
24361 use Composer\DependencyResolver\PolicyInterface;
24362 use Composer\DependencyResolver\Operation\OperationInterface;
24363 use Composer\DependencyResolver\Pool;
24364 use Composer\DependencyResolver\Request;
24365 use Composer\EventDispatcher\Event;
24366 use Composer\IO\IOInterface;
24367 use Composer\Repository\CompositeRepository;
24368
24369
24370
24371
24372
24373
24374 class InstallerEvent extends Event
24375 {
24376
24377
24378
24379 private $composer;
24380
24381
24382
24383
24384 private $io;
24385
24386
24387
24388
24389 private $devMode;
24390
24391
24392
24393
24394 private $policy;
24395
24396
24397
24398
24399 private $pool;
24400
24401
24402
24403
24404 private $installedRepo;
24405
24406
24407
24408
24409 private $request;
24410
24411
24412
24413
24414 private $operations;
24415
24416
24417
24418
24419
24420
24421
24422
24423
24424
24425
24426
24427
24428
24429 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
24430 {
24431 parent::__construct($eventName);
24432
24433 $this->composer = $composer;
24434 $this->io = $io;
24435 $this->devMode = $devMode;
24436 $this->policy = $policy;
24437 $this->pool = $pool;
24438 $this->installedRepo = $installedRepo;
24439 $this->request = $request;
24440 $this->operations = $operations;
24441 }
24442
24443
24444
24445
24446 public function getComposer()
24447 {
24448 return $this->composer;
24449 }
24450
24451
24452
24453
24454 public function getIO()
24455 {
24456 return $this->io;
24457 }
24458
24459
24460
24461
24462 public function isDevMode()
24463 {
24464 return $this->devMode;
24465 }
24466
24467
24468
24469
24470 public function getPolicy()
24471 {
24472 return $this->policy;
24473 }
24474
24475
24476
24477
24478 public function getPool()
24479 {
24480 return $this->pool;
24481 }
24482
24483
24484
24485
24486 public function getInstalledRepo()
24487 {
24488 return $this->installedRepo;
24489 }
24490
24491
24492
24493
24494 public function getRequest()
24495 {
24496 return $this->request;
24497 }
24498
24499
24500
24501
24502 public function getOperations()
24503 {
24504 return $this->operations;
24505 }
24506 }
24507 <?php
24508
24509
24510
24511
24512
24513
24514
24515
24516
24517
24518
24519 namespace Composer\Installer;
24520
24521
24522
24523
24524
24525
24526 class InstallerEvents
24527 {
24528
24529
24530
24531
24532
24533
24534
24535
24536
24537 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
24538
24539
24540
24541
24542
24543
24544
24545
24546
24547
24548 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
24549 }
24550 <?php
24551
24552
24553
24554
24555
24556
24557
24558
24559
24560
24561
24562 namespace Composer\Installer;
24563
24564 use Composer\Package\PackageInterface;
24565 use Composer\Repository\InstalledRepositoryInterface;
24566 use InvalidArgumentException;
24567
24568
24569
24570
24571
24572
24573
24574 interface InstallerInterface
24575 {
24576
24577
24578
24579
24580
24581
24582 public function supports($packageType);
24583
24584
24585
24586
24587
24588
24589
24590
24591
24592 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
24593
24594
24595
24596
24597
24598
24599
24600 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
24601
24602
24603
24604
24605
24606
24607
24608
24609
24610
24611 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
24612
24613
24614
24615
24616
24617
24618
24619 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
24620
24621
24622
24623
24624
24625
24626
24627 public function getInstallPath(PackageInterface $package);
24628 }
24629 <?php
24630
24631
24632
24633
24634
24635
24636
24637
24638
24639
24640
24641 namespace Composer\Installer;
24642
24643 use Composer\Composer;
24644 use Composer\IO\IOInterface;
24645 use Composer\Repository\InstalledRepositoryInterface;
24646 use Composer\Package\PackageInterface;
24647 use Composer\Util\Filesystem;
24648 use Composer\Util\Silencer;
24649 use Composer\Util\Platform;
24650
24651
24652
24653
24654
24655
24656
24657 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
24658 {
24659 protected $composer;
24660 protected $vendorDir;
24661 protected $binDir;
24662 protected $downloadManager;
24663 protected $io;
24664 protected $type;
24665 protected $filesystem;
24666 protected $binCompat;
24667 protected $binaryInstaller;
24668
24669
24670
24671
24672
24673
24674
24675
24676
24677
24678 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
24679 {
24680 $this->composer = $composer;
24681 $this->downloadManager = $composer->getDownloadManager();
24682 $this->io = $io;
24683 $this->type = $type;
24684
24685 $this->filesystem = $filesystem ?: new Filesystem();
24686 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
24687 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
24688 }
24689
24690
24691
24692
24693 public function supports($packageType)
24694 {
24695 return $packageType === $this->type || null === $this->type;
24696 }
24697
24698
24699
24700
24701 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24702 {
24703 if (!$repo->hasPackage($package)) {
24704 return false;
24705 }
24706
24707 $installPath = $this->getInstallPath($package);
24708
24709 if (is_readable($installPath)) {
24710 return true;
24711 }
24712
24713 return (Platform::isWindows() && $this->filesystem->isJunction($installPath)) || is_link($installPath);
24714 }
24715
24716
24717
24718
24719 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24720 {
24721 $this->initializeVendorDir();
24722 $downloadPath = $this->getInstallPath($package);
24723
24724
24725 if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
24726 $this->binaryInstaller->removeBinaries($package);
24727 }
24728
24729 $this->installCode($package);
24730 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
24731 if (!$repo->hasPackage($package)) {
24732 $repo->addPackage(clone $package);
24733 }
24734 }
24735
24736
24737
24738
24739 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24740 {
24741 if (!$repo->hasPackage($initial)) {
24742 throw new \InvalidArgumentException('Package is not installed: '.$initial);
24743 }
24744
24745 $this->initializeVendorDir();
24746
24747 $this->binaryInstaller->removeBinaries($initial);
24748 $this->updateCode($initial, $target);
24749 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
24750 $repo->removePackage($initial);
24751 if (!$repo->hasPackage($target)) {
24752 $repo->addPackage(clone $target);
24753 }
24754 }
24755
24756
24757
24758
24759 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
24760 {
24761 if (!$repo->hasPackage($package)) {
24762 throw new \InvalidArgumentException('Package is not installed: '.$package);
24763 }
24764
24765 $this->removeCode($package);
24766 $this->binaryInstaller->removeBinaries($package);
24767 $repo->removePackage($package);
24768
24769 $downloadPath = $this->getPackageBasePath($package);
24770 if (strpos($package->getName(), '/')) {
24771 $packageVendorDir = dirname($downloadPath);
24772 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
24773 Silencer::call('rmdir', $packageVendorDir);
24774 }
24775 }
24776 }
24777
24778
24779
24780
24781 public function getInstallPath(PackageInterface $package)
24782 {
24783 $this->initializeVendorDir();
24784
24785 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
24786 $targetDir = $package->getTargetDir();
24787
24788 return $basePath . ($targetDir ? '/'.$targetDir : '');
24789 }
24790
24791
24792
24793
24794
24795
24796 public function ensureBinariesPresence(PackageInterface $package)
24797 {
24798 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
24799 }
24800
24801
24802
24803
24804
24805
24806
24807
24808
24809
24810 protected function getPackageBasePath(PackageInterface $package)
24811 {
24812 $installPath = $this->getInstallPath($package);
24813 $targetDir = $package->getTargetDir();
24814
24815 if ($targetDir) {
24816 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
24817 }
24818
24819 return $installPath;
24820 }
24821
24822 protected function installCode(PackageInterface $package)
24823 {
24824 $downloadPath = $this->getInstallPath($package);
24825 $this->downloadManager->download($package, $downloadPath);
24826 }
24827
24828 protected function updateCode(PackageInterface $initial, PackageInterface $target)
24829 {
24830 $initialDownloadPath = $this->getInstallPath($initial);
24831 $targetDownloadPath = $this->getInstallPath($target);
24832 if ($targetDownloadPath !== $initialDownloadPath) {
24833
24834
24835 if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
24836 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
24837 ) {
24838 $this->removeCode($initial);
24839 $this->installCode($target);
24840
24841 return;
24842 }
24843
24844 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
24845 }
24846 $this->downloadManager->update($initial, $target, $targetDownloadPath);
24847 }
24848
24849 protected function removeCode(PackageInterface $package)
24850 {
24851 $downloadPath = $this->getPackageBasePath($package);
24852 $this->downloadManager->remove($package, $downloadPath);
24853 }
24854
24855 protected function initializeVendorDir()
24856 {
24857 $this->filesystem->ensureDirectoryExists($this->vendorDir);
24858 $this->vendorDir = realpath($this->vendorDir);
24859 }
24860 }
24861 <?php
24862
24863
24864
24865
24866
24867
24868
24869
24870
24871
24872
24873 namespace Composer\Installer;
24874
24875 use Composer\Repository\InstalledRepositoryInterface;
24876 use Composer\Package\PackageInterface;
24877 use Composer\Package\Version\VersionParser;
24878 use Composer\IO\IOInterface;
24879
24880
24881
24882
24883
24884
24885 class MetapackageInstaller implements InstallerInterface
24886 {
24887 private $io;
24888
24889 public function __construct(IOInterface $io)
24890 {
24891 $this->io = $io;
24892 }
24893
24894
24895
24896
24897 public function supports($packageType)
24898 {
24899 return $packageType === 'metapackage';
24900 }
24901
24902
24903
24904
24905 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24906 {
24907 return $repo->hasPackage($package);
24908 }
24909
24910
24911
24912
24913 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24914 {
24915 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
24916
24917 $repo->addPackage(clone $package);
24918 }
24919
24920
24921
24922
24923 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24924 {
24925 if (!$repo->hasPackage($initial)) {
24926 throw new \InvalidArgumentException('Package is not installed: '.$initial);
24927 }
24928
24929 $name = $target->getName();
24930 $from = $initial->getFullPrettyVersion();
24931 $to = $target->getFullPrettyVersion();
24932 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
24933 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>)");
24934
24935 $repo->removePackage($initial);
24936 $repo->addPackage(clone $target);
24937 }
24938
24939
24940
24941
24942 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
24943 {
24944 if (!$repo->hasPackage($package)) {
24945 throw new \InvalidArgumentException('Package is not installed: '.$package);
24946 }
24947
24948 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
24949
24950 $repo->removePackage($package);
24951 }
24952
24953
24954
24955
24956 public function getInstallPath(PackageInterface $package)
24957 {
24958 return '';
24959 }
24960 }
24961 <?php
24962
24963
24964
24965
24966
24967
24968
24969
24970
24971
24972
24973 namespace Composer\Installer;
24974
24975 use Composer\Repository\InstalledRepositoryInterface;
24976 use Composer\Package\PackageInterface;
24977
24978
24979
24980
24981
24982
24983
24984
24985 class NoopInstaller implements InstallerInterface
24986 {
24987
24988
24989
24990 public function supports($packageType)
24991 {
24992 return true;
24993 }
24994
24995
24996
24997
24998 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24999 {
25000 return $repo->hasPackage($package);
25001 }
25002
25003
25004
25005
25006 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
25007 {
25008 if (!$repo->hasPackage($package)) {
25009 $repo->addPackage(clone $package);
25010 }
25011 }
25012
25013
25014
25015
25016 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
25017 {
25018 if (!$repo->hasPackage($initial)) {
25019 throw new \InvalidArgumentException('Package is not installed: '.$initial);
25020 }
25021
25022 $repo->removePackage($initial);
25023 if (!$repo->hasPackage($target)) {
25024 $repo->addPackage(clone $target);
25025 }
25026 }
25027
25028
25029
25030
25031 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
25032 {
25033 if (!$repo->hasPackage($package)) {
25034 throw new \InvalidArgumentException('Package is not installed: '.$package);
25035 }
25036 $repo->removePackage($package);
25037 }
25038
25039
25040
25041
25042 public function getInstallPath(PackageInterface $package)
25043 {
25044 $targetDir = $package->getTargetDir();
25045
25046 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
25047 }
25048 }
25049 <?php
25050
25051
25052
25053
25054
25055
25056
25057
25058
25059
25060
25061 namespace Composer\Installer;
25062
25063 use Composer\Composer;
25064 use Composer\IO\IOInterface;
25065 use Composer\DependencyResolver\Operation\OperationInterface;
25066 use Composer\DependencyResolver\PolicyInterface;
25067 use Composer\DependencyResolver\Pool;
25068 use Composer\DependencyResolver\Request;
25069 use Composer\Repository\CompositeRepository;
25070
25071
25072
25073
25074
25075
25076 class PackageEvent extends InstallerEvent
25077 {
25078
25079
25080
25081 private $operation;
25082
25083
25084
25085
25086
25087
25088
25089
25090
25091
25092
25093
25094
25095
25096
25097 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
25098 {
25099 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
25100
25101 $this->operation = $operation;
25102 }
25103
25104
25105
25106
25107
25108
25109 public function getOperation()
25110 {
25111 return $this->operation;
25112 }
25113 }
25114 <?php
25115
25116
25117
25118
25119
25120
25121
25122
25123
25124
25125
25126 namespace Composer\Installer;
25127
25128
25129
25130
25131
25132
25133 class PackageEvents
25134 {
25135
25136
25137
25138
25139
25140
25141
25142 const PRE_PACKAGE_INSTALL = 'pre-package-install';
25143
25144
25145
25146
25147
25148
25149
25150
25151 const POST_PACKAGE_INSTALL = 'post-package-install';
25152
25153
25154
25155
25156
25157
25158
25159
25160 const PRE_PACKAGE_UPDATE = 'pre-package-update';
25161
25162
25163
25164
25165
25166
25167
25168
25169 const POST_PACKAGE_UPDATE = 'post-package-update';
25170
25171
25172
25173
25174
25175
25176
25177
25178 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
25179
25180
25181
25182
25183
25184
25185
25186
25187 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
25188 }
25189 <?php
25190
25191
25192
25193
25194
25195
25196
25197
25198
25199
25200
25201 namespace Composer\Installer;
25202
25203 use Composer\IO\IOInterface;
25204 use Composer\Package\PackageInterface;
25205 use Composer\Util\Filesystem;
25206 use Composer\Util\ProcessExecutor;
25207
25208
25209
25210
25211
25212
25213 class PearBinaryInstaller extends BinaryInstaller
25214 {
25215 private $installer;
25216 private $vendorDir;
25217
25218
25219
25220
25221
25222
25223
25224
25225
25226 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
25227 {
25228 parent::__construct($io, $binDir, $binCompat, $filesystem);
25229 $this->installer = $installer;
25230 $this->vendorDir = $vendorDir;
25231 }
25232
25233 protected function getBinaries(PackageInterface $package)
25234 {
25235 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
25236 $binaries = array();
25237 if (file_exists($binariesPath)) {
25238 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
25239 if (!$value->isDir()) {
25240 $binaries[] = 'bin/'.$fileName;
25241 }
25242 }
25243 }
25244
25245 return $binaries;
25246 }
25247
25248 protected function initializeBinDir()
25249 {
25250 parent::initializeBinDir();
25251 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
25252 @chmod($this->binDir.'/composer-php', 0777 & ~umask());
25253 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
25254 @chmod($this->binDir.'/composer-php.bat', 0777 & ~umask());
25255 }
25256
25257 protected function generateWindowsProxyCode($bin, $link)
25258 {
25259 $binPath = $this->filesystem->findShortestPath($link, $bin);
25260 if ('.bat' === substr($bin, -4)) {
25261 $caller = 'call';
25262 } else {
25263 $handle = fopen($bin, 'r');
25264 $line = fgets($handle);
25265 fclose($handle);
25266 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
25267 $caller = trim($match[1]);
25268 } else {
25269 $caller = 'php';
25270 }
25271
25272 if ($caller === 'php') {
25273 return "@echo off\r\n".
25274 "pushd .\r\n".
25275 "cd %~dp0\r\n".
25276 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
25277 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
25278 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
25279 "popd\r\n".
25280 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
25281 }
25282 }
25283
25284 return "@echo off\r\n".
25285 "pushd .\r\n".
25286 "cd %~dp0\r\n".
25287 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
25288 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
25289 "popd\r\n".
25290 $caller." \"%BIN_TARGET%\" %*\r\n";
25291 }
25292
25293 private function generateWindowsPhpProxyCode()
25294 {
25295 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
25296
25297 return
25298 "@echo off\r\n" .
25299 "setlocal enabledelayedexpansion\r\n" .
25300 "set BIN_DIR=%~dp0\r\n" .
25301 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
25302 "set DIRS=.\r\n" .
25303 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
25304 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
25305 "        set DIRS=!DIRS!;%%~fP\r\n" .
25306 "    )\r\n" .
25307 ")\r\n" .
25308 "php.exe -d include_path=!DIRS! %*\r\n";
25309 }
25310
25311 private function generateUnixyPhpProxyCode()
25312 {
25313 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
25314
25315 return
25316 "#!/usr/bin/env sh\n".
25317 "SRC_DIR=`pwd`\n".
25318 "BIN_DIR=`dirname $0`\n".
25319 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
25320 "DIRS=\"\"\n".
25321 "for vendor in \$VENDOR_DIR/*; do\n".
25322 "    if [ -d \"\$vendor\" ]; then\n".
25323 "        for package in \$vendor/*; do\n".
25324 "            if [ -d \"\$package\" ]; then\n".
25325 "                DIRS=\"\${DIRS}:\${package}\"\n".
25326 "            fi\n".
25327 "        done\n".
25328 "    fi\n".
25329 "done\n".
25330 "php -d include_path=\".\$DIRS\" $@\n";
25331 }
25332 }
25333 <?php
25334
25335
25336
25337
25338
25339
25340
25341
25342
25343
25344
25345 namespace Composer\Installer;
25346
25347 use Composer\IO\IOInterface;
25348 use Composer\Composer;
25349 use Composer\Downloader\PearPackageExtractor;
25350 use Composer\Repository\InstalledRepositoryInterface;
25351 use Composer\Package\PackageInterface;
25352 use Composer\Util\Platform;
25353 use Composer\Util\Filesystem;
25354
25355
25356
25357
25358
25359
25360
25361 class PearInstaller extends LibraryInstaller
25362 {
25363
25364
25365
25366
25367
25368
25369
25370 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
25371 {
25372 $filesystem = new Filesystem();
25373 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
25374
25375 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
25376 }
25377
25378
25379
25380
25381 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
25382 {
25383 $this->uninstall($repo, $initial);
25384 $this->install($repo, $target);
25385 }
25386
25387 protected function installCode(PackageInterface $package)
25388 {
25389 parent::installCode($package);
25390
25391 $isWindows = Platform::isWindows();
25392 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
25393
25394 if (!$isWindows) {
25395 $php_bin = '/usr/bin/env ' . $php_bin;
25396 }
25397
25398 $installPath = $this->getInstallPath($package);
25399 $vars = array(
25400 'os' => $isWindows ? 'windows' : 'linux',
25401 'php_bin' => $php_bin,
25402 'pear_php' => $installPath,
25403 'php_dir' => $installPath,
25404 'bin_dir' => $installPath . '/bin',
25405 'data_dir' => $installPath . '/data',
25406 'version' => $package->getPrettyVersion(),
25407 );
25408
25409 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
25410 $pearExtractor = new PearPackageExtractor($packageArchive);
25411 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
25412
25413 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
25414 $this->filesystem->unlink($packageArchive);
25415 }
25416 }
25417 <?php
25418
25419
25420
25421
25422
25423
25424
25425
25426
25427
25428
25429 namespace Composer\Installer;
25430
25431 use Composer\Composer;
25432 use Composer\IO\IOInterface;
25433 use Composer\Repository\InstalledRepositoryInterface;
25434 use Composer\Package\PackageInterface;
25435
25436
25437
25438
25439
25440
25441
25442 class PluginInstaller extends LibraryInstaller
25443 {
25444 private $installationManager;
25445
25446
25447
25448
25449
25450
25451
25452 public function __construct(IOInterface $io, Composer $composer)
25453 {
25454 parent::__construct($io, $composer, 'composer-plugin');
25455 $this->installationManager = $composer->getInstallationManager();
25456 }
25457
25458
25459
25460
25461 public function supports($packageType)
25462 {
25463 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
25464 }
25465
25466
25467
25468
25469 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
25470 {
25471 $extra = $package->getExtra();
25472 if (empty($extra['class'])) {
25473 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
25474 }
25475
25476 parent::install($repo, $package);
25477 try {
25478 $this->composer->getPluginManager()->registerPackage($package, true);
25479 } catch (\Exception $e) {
25480
25481 $this->io->writeError('Plugin installation failed ('.$e->getMessage().'), rolling back');
25482 parent::uninstall($repo, $package);
25483 throw $e;
25484 }
25485 }
25486
25487
25488
25489
25490 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
25491 {
25492 $extra = $target->getExtra();
25493 if (empty($extra['class'])) {
25494 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
25495 }
25496
25497 parent::update($repo, $initial, $target);
25498 $this->composer->getPluginManager()->registerPackage($target, true);
25499 }
25500 }
25501 <?php
25502
25503
25504
25505
25506
25507
25508
25509
25510
25511
25512
25513 namespace Composer\Installer;
25514
25515 use Composer\Package\PackageInterface;
25516 use Composer\Downloader\DownloadManager;
25517 use Composer\Repository\InstalledRepositoryInterface;
25518 use Composer\Util\Filesystem;
25519
25520
25521
25522
25523
25524
25525
25526 class ProjectInstaller implements InstallerInterface
25527 {
25528 private $installPath;
25529 private $downloadManager;
25530 private $filesystem;
25531
25532 public function __construct($installPath, DownloadManager $dm)
25533 {
25534 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
25535 $this->downloadManager = $dm;
25536 $this->filesystem = new Filesystem;
25537 }
25538
25539
25540
25541
25542
25543
25544
25545 public function supports($packageType)
25546 {
25547 return true;
25548 }
25549
25550
25551
25552
25553 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
25554 {
25555 return false;
25556 }
25557
25558
25559
25560
25561 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
25562 {
25563 $installPath = $this->installPath;
25564 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
25565 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
25566 }
25567 if (!is_dir($installPath)) {
25568 mkdir($installPath, 0777, true);
25569 }
25570 $this->downloadManager->download($package, $installPath);
25571 }
25572
25573
25574
25575
25576 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
25577 {
25578 throw new \InvalidArgumentException("not supported");
25579 }
25580
25581
25582
25583
25584 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
25585 {
25586 throw new \InvalidArgumentException("not supported");
25587 }
25588
25589
25590
25591
25592
25593
25594
25595 public function getInstallPath(PackageInterface $package)
25596 {
25597 return $this->installPath;
25598 }
25599 }
25600 <?php
25601
25602
25603
25604
25605
25606
25607
25608
25609
25610
25611
25612 namespace Composer\Installer;
25613
25614 use Composer\IO\IOInterface;
25615 use Composer\Package\PackageInterface;
25616 use Composer\Repository\RepositoryInterface;
25617 use Symfony\Component\Console\Formatter\OutputFormatter;
25618
25619
25620
25621
25622
25623
25624 class SuggestedPackagesReporter
25625 {
25626
25627
25628
25629 protected $suggestedPackages = array();
25630
25631
25632
25633
25634 private $io;
25635
25636 public function __construct(IOInterface $io)
25637 {
25638 $this->io = $io;
25639 }
25640
25641
25642
25643
25644 public function getPackages()
25645 {
25646 return $this->suggestedPackages;
25647 }
25648
25649
25650
25651
25652
25653
25654
25655
25656
25657
25658
25659
25660 public function addPackage($source, $target, $reason)
25661 {
25662 $this->suggestedPackages[] = array(
25663 'source' => $source,
25664 'target' => $target,
25665 'reason' => $reason,
25666 );
25667
25668 return $this;
25669 }
25670
25671
25672
25673
25674
25675
25676
25677 public function addSuggestionsFromPackage(PackageInterface $package)
25678 {
25679 $source = $package->getPrettyName();
25680 foreach ($package->getSuggests() as $target => $reason) {
25681 $this->addPackage(
25682 $source,
25683 $target,
25684 $reason
25685 );
25686 }
25687
25688 return $this;
25689 }
25690
25691
25692
25693
25694
25695
25696
25697
25698 public function output(RepositoryInterface $installedRepo = null)
25699 {
25700 $suggestedPackages = $this->getPackages();
25701 $installedPackages = array();
25702 if (null !== $installedRepo && ! empty($suggestedPackages)) {
25703 foreach ($installedRepo->getPackages() as $package) {
25704 $installedPackages = array_merge(
25705 $installedPackages,
25706 $package->getNames()
25707 );
25708 }
25709 }
25710
25711 foreach ($suggestedPackages as $suggestion) {
25712 if (in_array($suggestion['target'], $installedPackages)) {
25713 continue;
25714 }
25715
25716 $this->io->writeError(sprintf(
25717 '%s suggests installing %s%s',
25718 $suggestion['source'],
25719 $this->escapeOutput($suggestion['target']),
25720 $this->escapeOutput('' !== $suggestion['reason'] ? ' ('.$suggestion['reason'].')' : '')
25721 ));
25722 }
25723
25724 return $this;
25725 }
25726
25727
25728
25729
25730
25731 private function escapeOutput($string)
25732 {
25733 return OutputFormatter::escape(
25734 $this->removeControlCharacters($string)
25735 );
25736 }
25737
25738
25739
25740
25741
25742 private function removeControlCharacters($string)
25743 {
25744 return preg_replace(
25745 '/[[:cntrl:]]/',
25746 '',
25747 str_replace("\n", ' ', $string)
25748 );
25749 }
25750 }
25751 <?php
25752
25753
25754
25755
25756
25757
25758
25759
25760
25761
25762
25763 namespace Composer\Json;
25764
25765 use JsonSchema\Validator;
25766 use Seld\JsonLint\JsonParser;
25767 use Seld\JsonLint\ParsingException;
25768 use Composer\Util\RemoteFilesystem;
25769 use Composer\IO\IOInterface;
25770 use Composer\Downloader\TransportException;
25771
25772
25773
25774
25775
25776
25777
25778 class JsonFile
25779 {
25780 const LAX_SCHEMA = 1;
25781 const STRICT_SCHEMA = 2;
25782
25783 const JSON_UNESCAPED_SLASHES = 64;
25784 const JSON_PRETTY_PRINT = 128;
25785 const JSON_UNESCAPED_UNICODE = 256;
25786
25787 const COMPOSER_SCHEMA_PATH = '/../../../res/composer-schema.json';
25788
25789 private $path;
25790 private $rfs;
25791 private $io;
25792
25793
25794
25795
25796
25797
25798
25799
25800
25801 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
25802 {
25803 $this->path = $path;
25804
25805 if (null === $rfs && preg_match('{^https?://}i', $path)) {
25806 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
25807 }
25808 $this->rfs = $rfs;
25809 $this->io = $io;
25810 }
25811
25812
25813
25814
25815 public function getPath()
25816 {
25817 return $this->path;
25818 }
25819
25820
25821
25822
25823
25824
25825 public function exists()
25826 {
25827 return is_file($this->path);
25828 }
25829
25830
25831
25832
25833
25834
25835
25836 public function read()
25837 {
25838 try {
25839 if ($this->rfs) {
25840 $json = $this->rfs->getContents($this->path, $this->path, false);
25841 } else {
25842 if ($this->io && $this->io->isDebug()) {
25843 $this->io->writeError('Reading ' . $this->path);
25844 }
25845 $json = file_get_contents($this->path);
25846 }
25847 } catch (TransportException $e) {
25848 throw new \RuntimeException($e->getMessage(), 0, $e);
25849 } catch (\Exception $e) {
25850 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
25851 }
25852
25853 return static::parseJson($json, $this->path);
25854 }
25855
25856
25857
25858
25859
25860
25861
25862
25863 public function write(array $hash, $options = 448)
25864 {
25865 $dir = dirname($this->path);
25866 if (!is_dir($dir)) {
25867 if (file_exists($dir)) {
25868 throw new \UnexpectedValueException(
25869 $dir.' exists and is not a directory.'
25870 );
25871 }
25872 if (!@mkdir($dir, 0777, true)) {
25873 throw new \UnexpectedValueException(
25874 $dir.' does not exist and could not be created.'
25875 );
25876 }
25877 }
25878
25879 $retries = 3;
25880 while ($retries--) {
25881 try {
25882 $this->filePutContentsIfModified($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
25883 break;
25884 } catch (\Exception $e) {
25885 if ($retries) {
25886 usleep(500000);
25887 continue;
25888 }
25889
25890 throw $e;
25891 }
25892 }
25893 }
25894
25895
25896
25897
25898 private function filePutContentsIfModified($path, $content)
25899 {
25900 $currentContent = @file_get_contents($path);
25901 if (!$currentContent || ($currentContent != $content)) {
25902 return file_put_contents($path, $content);
25903 }
25904
25905 return 0;
25906 }
25907
25908
25909
25910
25911
25912
25913
25914
25915
25916 public function validateSchema($schema = self::STRICT_SCHEMA, $schemaFile = null)
25917 {
25918 $content = file_get_contents($this->path);
25919 $data = json_decode($content);
25920
25921 if (null === $data && 'null' !== $content) {
25922 self::validateSyntax($content, $this->path);
25923 }
25924
25925 if (null === $schemaFile) {
25926 $schemaFile = __DIR__ . self::COMPOSER_SCHEMA_PATH;
25927 }
25928
25929
25930 if (false === strpos($schemaFile, '://')) {
25931 $schemaFile = 'file://' . $schemaFile;
25932 }
25933
25934 $schemaData = (object) array('$ref' => $schemaFile);
25935
25936 if ($schema === self::LAX_SCHEMA) {
25937 $schemaData->additionalProperties = true;
25938 $schemaData->required = array();
25939 }
25940
25941 $validator = new Validator();
25942 $validator->check($data, $schemaData);
25943
25944
25945
25946 if (!$validator->isValid()) {
25947 $errors = array();
25948 foreach ((array) $validator->getErrors() as $error) {
25949 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
25950 }
25951 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
25952 }
25953
25954 return true;
25955 }
25956
25957
25958
25959
25960
25961
25962
25963
25964 public static function encode($data, $options = 448)
25965 {
25966 if (PHP_VERSION_ID >= 50400) {
25967 $json = json_encode($data, $options);
25968 if (false === $json) {
25969 self::throwEncodeError(json_last_error());
25970 }
25971
25972
25973 if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
25974 $json = preg_replace('/\[\s+\]/', '[]', $json);
25975 $json = preg_replace('/\{\s+\}/', '{}', $json);
25976 }
25977
25978 return $json;
25979 }
25980
25981 $json = json_encode($data);
25982 if (false === $json) {
25983 self::throwEncodeError(json_last_error());
25984 }
25985
25986 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
25987 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
25988 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
25989
25990 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
25991 return $json;
25992 }
25993
25994 return JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
25995 }
25996
25997
25998
25999
26000
26001
26002
26003 private static function throwEncodeError($code)
26004 {
26005 switch ($code) {
26006 case JSON_ERROR_DEPTH:
26007 $msg = 'Maximum stack depth exceeded';
26008 break;
26009 case JSON_ERROR_STATE_MISMATCH:
26010 $msg = 'Underflow or the modes mismatch';
26011 break;
26012 case JSON_ERROR_CTRL_CHAR:
26013 $msg = 'Unexpected control character found';
26014 break;
26015 case JSON_ERROR_UTF8:
26016 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
26017 break;
26018 default:
26019 $msg = 'Unknown error';
26020 }
26021
26022 throw new \RuntimeException('JSON encoding failed: '.$msg);
26023 }
26024
26025
26026
26027
26028
26029
26030
26031
26032
26033 public static function parseJson($json, $file = null)
26034 {
26035 if (null === $json) {
26036 return;
26037 }
26038 $data = json_decode($json, true);
26039 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
26040 self::validateSyntax($json, $file);
26041 }
26042
26043 return $data;
26044 }
26045
26046
26047
26048
26049
26050
26051
26052
26053
26054
26055 protected static function validateSyntax($json, $file = null)
26056 {
26057 $parser = new JsonParser();
26058 $result = $parser->lint($json);
26059 if (null === $result) {
26060 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
26061 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
26062 }
26063
26064 return true;
26065 }
26066
26067 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
26068 }
26069 }
26070 <?php
26071
26072
26073
26074
26075
26076
26077
26078
26079
26080
26081
26082 namespace Composer\Json;
26083
26084
26085
26086
26087
26088
26089
26090
26091
26092 class JsonFormatter
26093 {
26094
26095
26096
26097
26098
26099
26100
26101
26102
26103
26104
26105
26106 public static function format($json, $unescapeUnicode, $unescapeSlashes)
26107 {
26108 $result = '';
26109 $pos = 0;
26110 $strLen = strlen($json);
26111 $indentStr = '    ';
26112 $newLine = "\n";
26113 $outOfQuotes = true;
26114 $buffer = '';
26115 $noescape = true;
26116
26117 for ($i = 0; $i < $strLen; $i++) {
26118
26119 $char = substr($json, $i, 1);
26120
26121
26122 if ('"' === $char && $noescape) {
26123 $outOfQuotes = !$outOfQuotes;
26124 }
26125
26126 if (!$outOfQuotes) {
26127 $buffer .= $char;
26128 $noescape = '\\' === $char ? !$noescape : true;
26129 continue;
26130 } elseif ('' !== $buffer) {
26131 if ($unescapeSlashes) {
26132 $buffer = str_replace('\\/', '/', $buffer);
26133 }
26134
26135 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
26136
26137 $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
26138 $l = strlen($match[1]);
26139
26140 if ($l % 2) {
26141 $code = hexdec($match[2]);
26142
26143
26144 if (0xD800 <= $code && 0xDFFF >= $code) {
26145 return $match[0];
26146 }
26147
26148 return str_repeat('\\', $l - 1) . mb_convert_encoding(
26149 pack('H*', $match[2]),
26150 'UTF-8',
26151 'UCS-2BE'
26152 );
26153 }
26154
26155 return $match[0];
26156 }, $buffer);
26157 }
26158
26159 $result .= $buffer.$char;
26160 $buffer = '';
26161 continue;
26162 }
26163
26164 if (':' === $char) {
26165
26166 $char .= ' ';
26167 } elseif ('}' === $char || ']' === $char) {
26168 $pos--;
26169 $prevChar = substr($json, $i - 1, 1);
26170
26171 if ('{' !== $prevChar && '[' !== $prevChar) {
26172
26173
26174 $result .= $newLine;
26175 for ($j = 0; $j < $pos; $j++) {
26176 $result .= $indentStr;
26177 }
26178 } else {
26179
26180 $result = rtrim($result);
26181 }
26182 }
26183
26184 $result .= $char;
26185
26186
26187
26188 if (',' === $char || '{' === $char || '[' === $char) {
26189 $result .= $newLine;
26190
26191 if ('{' === $char || '[' === $char) {
26192 $pos++;
26193 }
26194
26195 for ($j = 0; $j < $pos; $j++) {
26196 $result .= $indentStr;
26197 }
26198 }
26199 }
26200
26201 return $result;
26202 }
26203 }
26204 <?php
26205
26206
26207
26208
26209
26210
26211
26212
26213
26214
26215
26216 namespace Composer\Json;
26217
26218 use Composer\Repository\PlatformRepository;
26219
26220
26221
26222
26223 class JsonManipulator
26224 {
26225 private static $DEFINES = '(?(DEFINE)
26226        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
26227        (?<boolean>   true | false | null )
26228        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
26229        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
26230        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
26231        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
26232        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
26233     )';
26234
26235 private $contents;
26236 private $newline;
26237 private $indent;
26238
26239 public function __construct($contents)
26240 {
26241 $contents = trim($contents);
26242 if ($contents === '') {
26243 $contents = '{}';
26244 }
26245 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
26246 throw new \InvalidArgumentException('The json file must be an object ({})');
26247 }
26248 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
26249 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
26250 $this->detectIndenting();
26251 }
26252
26253 public function getContents()
26254 {
26255 return $this->contents . $this->newline;
26256 }
26257
26258 public function addLink($type, $package, $constraint, $sortPackages = false)
26259 {
26260 $decoded = JsonFile::parseJson($this->contents);
26261
26262
26263 if (!isset($decoded[$type])) {
26264 return $this->addMainKey($type, array($package => $constraint));
26265 }
26266
26267 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
26268 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
26269 if (!$this->pregMatch($regex, $this->contents, $matches)) {
26270 return false;
26271 }
26272
26273 $links = $matches['value'];
26274
26275
26276 $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
26277 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
26278 if ($this->pregMatch($regex, $links, $packageMatches)) {
26279
26280 $existingPackage = $packageMatches['package'];
26281 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
26282 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
26283 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
26284 }, $links);
26285 } else {
26286 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
26287
26288 $links = preg_replace(
26289 '{'.preg_quote($match[1]).'$}',
26290
26291 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
26292 $links
26293 );
26294 } else {
26295
26296 $links = '{' . $this->newline .
26297 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
26298 $this->indent . '}';
26299 }
26300 }
26301
26302 if (true === $sortPackages) {
26303 $requirements = json_decode($links, true);
26304 $this->sortPackages($requirements);
26305 $links = $this->format($requirements);
26306 }
26307
26308 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
26309
26310 return true;
26311 }
26312
26313
26314
26315
26316
26317
26318
26319
26320 private function sortPackages(array &$packages = array())
26321 {
26322 $prefix = function ($requirement) {
26323 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
26324 return preg_replace(
26325 array(
26326 '/^php/',
26327 '/^hhvm/',
26328 '/^ext/',
26329 '/^lib/',
26330 '/^\D/',
26331 ),
26332 array(
26333 '0-$0',
26334 '1-$0',
26335 '2-$0',
26336 '3-$0',
26337 '4-$0',
26338 ),
26339 $requirement
26340 );
26341 }
26342
26343 return '5-'.$requirement;
26344 };
26345
26346 uksort($packages, function ($a, $b) use ($prefix) {
26347 return strnatcmp($prefix($a), $prefix($b));
26348 });
26349 }
26350
26351 public function addRepository($name, $config)
26352 {
26353 return $this->addSubNode('repositories', $name, $config);
26354 }
26355
26356 public function removeRepository($name)
26357 {
26358 return $this->removeSubNode('repositories', $name);
26359 }
26360
26361 public function addConfigSetting($name, $value)
26362 {
26363 return $this->addSubNode('config', $name, $value);
26364 }
26365
26366 public function removeConfigSetting($name)
26367 {
26368 return $this->removeSubNode('config', $name);
26369 }
26370
26371 public function addProperty($name, $value)
26372 {
26373 if (substr($name, 0, 8) === 'suggest.') {
26374 return $this->addSubNode('suggest', substr($name, 8), $value);
26375 }
26376
26377 if (substr($name, 0, 6) === 'extra.') {
26378 return $this->addSubNode('extra', substr($name, 6), $value);
26379 }
26380
26381 if (substr($name, 0, 8) === 'scripts.') {
26382 return $this->addSubNode('scripts', substr($name, 8), $value);
26383 }
26384
26385 return $this->addMainKey($name, $value);
26386 }
26387
26388 public function removeProperty($name)
26389 {
26390 if (substr($name, 0, 8) === 'suggest.') {
26391 return $this->removeSubNode('suggest', substr($name, 8));
26392 }
26393
26394 if (substr($name, 0, 6) === 'extra.') {
26395 return $this->removeSubNode('extra', substr($name, 6));
26396 }
26397
26398 if (substr($name, 0, 8) === 'scripts.') {
26399 return $this->removeSubNode('scripts', substr($name, 8));
26400 }
26401
26402 return $this->removeMainKey($name);
26403 }
26404
26405 public function addSubNode($mainNode, $name, $value)
26406 {
26407 $decoded = JsonFile::parseJson($this->contents);
26408
26409 $subName = null;
26410 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
26411 list($name, $subName) = explode('.', $name, 2);
26412 }
26413
26414
26415 if (!isset($decoded[$mainNode])) {
26416 if ($subName !== null) {
26417 $this->addMainKey($mainNode, array($name => array($subName => $value)));
26418 } else {
26419 $this->addMainKey($mainNode, array($name => $value));
26420 }
26421
26422 return true;
26423 }
26424
26425
26426 $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
26427 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
26428
26429 try {
26430 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
26431 return false;
26432 }
26433 } catch (\RuntimeException $e) {
26434 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
26435 return false;
26436 }
26437 throw $e;
26438 }
26439
26440 $children = $match['content'];
26441
26442 if (!@json_decode($children)) {
26443 return false;
26444 }
26445
26446 $that = $this;
26447
26448
26449 $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
26450 if ($this->pregMatch($childRegex, $children, $matches)) {
26451 $children = preg_replace_callback($childRegex, function ($matches) use ($subName, $value, $that) {
26452 if ($subName !== null) {
26453 $curVal = json_decode($matches['content'], true);
26454 if (!is_array($curVal)) {
26455 $curVal = array();
26456 }
26457 $curVal[$subName] = $value;
26458 $value = $curVal;
26459 }
26460
26461 return $matches['start'] . $that->format($value, 1) . $matches['end'];
26462 }, $children);
26463 } else {
26464 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
26465
26466 $whitespace = '';
26467 if (!empty($match['trailingspace'])) {
26468 $whitespace = $match['trailingspace'];
26469 }
26470
26471 if (!empty($match['content'])) {
26472 if ($subName !== null) {
26473 $value = array($subName => $value);
26474 }
26475
26476
26477 $children = preg_replace(
26478 '#'.$whitespace.'}$#',
26479 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
26480 $children
26481 );
26482 } else {
26483 if ($subName !== null) {
26484 $value = array($subName => $value);
26485 }
26486
26487
26488 $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
26489 }
26490 }
26491
26492 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
26493 return $m['start'] . $children . $m['end'];
26494 }, $this->contents);
26495
26496 return true;
26497 }
26498
26499 public function removeSubNode($mainNode, $name)
26500 {
26501 $decoded = JsonFile::parseJson($this->contents);
26502
26503
26504 if (empty($decoded[$mainNode])) {
26505 return true;
26506 }
26507
26508
26509 $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
26510 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
26511 try {
26512 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
26513 return false;
26514 }
26515 } catch (\RuntimeException $e) {
26516 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
26517 return false;
26518 }
26519 throw $e;
26520 }
26521
26522 $children = $match['content'];
26523
26524
26525 if (!@json_decode($children, true)) {
26526 return false;
26527 }
26528
26529 $subName = null;
26530 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
26531 list($name, $subName) = explode('.', $name, 2);
26532 }
26533
26534
26535 if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
26536 return true;
26537 }
26538
26539
26540 $keyRegex = str_replace('/', '\\\\?/', preg_quote($name));
26541 if ($this->pregMatch('{"'.$keyRegex.'"\s*:}i', $children)) {
26542
26543 if (preg_match_all('{'.self::$DEFINES.'"'.$keyRegex.'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
26544 $bestMatch = '';
26545 foreach ($matches[0] as $match) {
26546 if (strlen($bestMatch) < strlen($match)) {
26547 $bestMatch = $match;
26548 }
26549 }
26550 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
26551 if (1 !== $count) {
26552 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
26553 if (1 !== $count) {
26554 return false;
26555 }
26556 }
26557 }
26558 } else {
26559 $childrenClean = $children;
26560 }
26561
26562
26563 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
26564 if (empty($match['content'])) {
26565 $newline = $this->newline;
26566 $indent = $this->indent;
26567
26568 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
26569 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
26570 }, $this->contents);
26571
26572
26573 if ($subName !== null) {
26574 $curVal = json_decode($children, true);
26575 unset($curVal[$name][$subName]);
26576 $this->addSubNode($mainNode, $name, $curVal[$name]);
26577 }
26578
26579 return true;
26580 }
26581
26582 $that = $this;
26583 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
26584 if ($subName !== null) {
26585 $curVal = json_decode($matches['content'], true);
26586 unset($curVal[$name][$subName]);
26587 $childrenClean = $that->format($curVal, 0);
26588 }
26589
26590 return $matches['start'] . $childrenClean . $matches['end'];
26591 }, $this->contents);
26592
26593 return true;
26594 }
26595
26596 public function addMainKey($key, $content)
26597 {
26598 $decoded = JsonFile::parseJson($this->contents);
26599 $content = $this->format($content);
26600
26601
26602 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
26603 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
26604 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
26605
26606 if (!@json_decode('{'.$matches['key'].'}')) {
26607 return false;
26608 }
26609
26610 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
26611
26612 return true;
26613 }
26614
26615
26616 if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
26617 $this->contents = preg_replace(
26618 '#'.$match[1].'\}$#',
26619 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
26620 $this->contents
26621 );
26622
26623 return true;
26624 }
26625
26626
26627 $this->contents = preg_replace(
26628 '#\}$#',
26629 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
26630 $this->contents
26631 );
26632
26633 return true;
26634 }
26635
26636 public function removeMainKey($key)
26637 {
26638 $decoded = JsonFile::parseJson($this->contents);
26639
26640 if (!array_key_exists($key, $decoded)) {
26641 return true;
26642 }
26643
26644
26645 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
26646 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
26647 if ($this->pregMatch($regex, $this->contents, $matches)) {
26648
26649 if (!@json_decode('{'.$matches['removal'].'}')) {
26650 return false;
26651 }
26652
26653
26654 if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
26655 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
26656 }
26657
26658 $this->contents = $matches['start'] . $matches['end'];
26659 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
26660 $this->contents = "{\n}";
26661 }
26662
26663 return true;
26664 }
26665
26666 return false;
26667 }
26668
26669 public function format($data, $depth = 0)
26670 {
26671 if (is_array($data)) {
26672 reset($data);
26673
26674 if (is_numeric(key($data))) {
26675 foreach ($data as $key => $val) {
26676 $data[$key] = $this->format($val, $depth + 1);
26677 }
26678
26679 return '['.implode(', ', $data).']';
26680 }
26681
26682 $out = '{' . $this->newline;
26683 $elems = array();
26684 foreach ($data as $key => $val) {
26685 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
26686 }
26687
26688 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
26689 }
26690
26691 return JsonFile::encode($data);
26692 }
26693
26694 protected function detectIndenting()
26695 {
26696 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
26697 $this->indent = $match[1];
26698 } else {
26699 $this->indent = '    ';
26700 }
26701 }
26702
26703 protected function pregMatch($re, $str, &$matches = array())
26704 {
26705 $count = preg_match($re, $str, $matches);
26706
26707 if ($count === false) {
26708 switch (preg_last_error()) {
26709 case PREG_NO_ERROR:
26710 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
26711 case PREG_INTERNAL_ERROR:
26712 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
26713 case PREG_BACKTRACK_LIMIT_ERROR:
26714 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
26715 case PREG_RECURSION_LIMIT_ERROR:
26716 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
26717 case PREG_BAD_UTF8_ERROR:
26718 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
26719 case PREG_BAD_UTF8_OFFSET_ERROR:
26720 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
26721 case 6: 
26722 if (PHP_VERSION_ID > 70000) {
26723 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
26724 }
26725
26726 default:
26727 throw new \RuntimeException('Failed to execute regex: Unknown error');
26728 }
26729 }
26730
26731 return $count;
26732 }
26733 }
26734 <?php
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744
26745
26746 namespace Composer\Json;
26747
26748 use Exception;
26749
26750
26751
26752
26753 class JsonValidationException extends Exception
26754 {
26755 protected $errors;
26756
26757 public function __construct($message, $errors = array(), Exception $previous = null)
26758 {
26759 $this->errors = $errors;
26760 parent::__construct($message, 0, $previous);
26761 }
26762
26763 public function getErrors()
26764 {
26765 return $this->errors;
26766 }
26767 }
26768 <?php
26769
26770
26771
26772
26773
26774
26775
26776
26777
26778
26779
26780 namespace Composer\Package;
26781
26782 use Composer\Semver\Constraint\Constraint;
26783 use Composer\Package\Version\VersionParser;
26784
26785
26786
26787
26788 class AliasPackage extends BasePackage implements CompletePackageInterface
26789 {
26790 protected $version;
26791 protected $prettyVersion;
26792 protected $dev;
26793 protected $rootPackageAlias = false;
26794 protected $stability;
26795
26796
26797 protected $aliasOf;
26798
26799 protected $requires;
26800
26801 protected $devRequires;
26802
26803 protected $conflicts;
26804
26805 protected $provides;
26806
26807 protected $replaces;
26808
26809
26810
26811
26812
26813
26814
26815
26816 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
26817 {
26818 parent::__construct($aliasOf->getName());
26819
26820 $this->version = $version;
26821 $this->prettyVersion = $prettyVersion;
26822 $this->aliasOf = $aliasOf;
26823 $this->stability = VersionParser::parseStability($version);
26824 $this->dev = $this->stability === 'dev';
26825
26826 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
26827 $links = $aliasOf->{'get' . ucfirst($type)}();
26828 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
26829 }
26830 }
26831
26832
26833
26834
26835 public function getAliasOf()
26836 {
26837 return $this->aliasOf;
26838 }
26839
26840
26841
26842
26843 public function getVersion()
26844 {
26845 return $this->version;
26846 }
26847
26848
26849
26850
26851 public function getStability()
26852 {
26853 return $this->stability;
26854 }
26855
26856
26857
26858
26859 public function getPrettyVersion()
26860 {
26861 return $this->prettyVersion;
26862 }
26863
26864
26865
26866
26867 public function isDev()
26868 {
26869 return $this->dev;
26870 }
26871
26872
26873
26874
26875 public function getRequires()
26876 {
26877 return $this->requires;
26878 }
26879
26880
26881
26882
26883 public function getConflicts()
26884 {
26885 return $this->conflicts;
26886 }
26887
26888
26889
26890
26891 public function getProvides()
26892 {
26893 return $this->provides;
26894 }
26895
26896
26897
26898
26899 public function getReplaces()
26900 {
26901 return $this->replaces;
26902 }
26903
26904
26905
26906
26907 public function getDevRequires()
26908 {
26909 return $this->devRequires;
26910 }
26911
26912
26913
26914
26915
26916
26917
26918
26919
26920
26921 public function setRootPackageAlias($value)
26922 {
26923 return $this->rootPackageAlias = $value;
26924 }
26925
26926
26927
26928
26929
26930 public function isRootPackageAlias()
26931 {
26932 return $this->rootPackageAlias;
26933 }
26934
26935
26936
26937
26938
26939
26940
26941 protected function replaceSelfVersionDependencies(array $links, $linkType)
26942 {
26943 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
26944 $newLinks = array();
26945 foreach ($links as $link) {
26946
26947 if ('self.version' === $link->getPrettyConstraint()) {
26948 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
26949 }
26950 }
26951 $links = array_merge($links, $newLinks);
26952 } else {
26953 foreach ($links as $index => $link) {
26954 if ('self.version' === $link->getPrettyConstraint()) {
26955 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
26956 }
26957 }
26958 }
26959
26960 return $links;
26961 }
26962
26963
26964
26965
26966
26967 public function getType()
26968 {
26969 return $this->aliasOf->getType();
26970 }
26971
26972 public function getTargetDir()
26973 {
26974 return $this->aliasOf->getTargetDir();
26975 }
26976
26977 public function getExtra()
26978 {
26979 return $this->aliasOf->getExtra();
26980 }
26981
26982 public function setInstallationSource($type)
26983 {
26984 $this->aliasOf->setInstallationSource($type);
26985 }
26986
26987 public function getInstallationSource()
26988 {
26989 return $this->aliasOf->getInstallationSource();
26990 }
26991
26992 public function getSourceType()
26993 {
26994 return $this->aliasOf->getSourceType();
26995 }
26996
26997 public function getSourceUrl()
26998 {
26999 return $this->aliasOf->getSourceUrl();
27000 }
27001
27002 public function getSourceUrls()
27003 {
27004 return $this->aliasOf->getSourceUrls();
27005 }
27006
27007 public function getSourceReference()
27008 {
27009 return $this->aliasOf->getSourceReference();
27010 }
27011
27012 public function setSourceReference($reference)
27013 {
27014 return $this->aliasOf->setSourceReference($reference);
27015 }
27016
27017 public function setSourceMirrors($mirrors)
27018 {
27019 return $this->aliasOf->setSourceMirrors($mirrors);
27020 }
27021
27022 public function getSourceMirrors()
27023 {
27024 return $this->aliasOf->getSourceMirrors();
27025 }
27026
27027 public function getDistType()
27028 {
27029 return $this->aliasOf->getDistType();
27030 }
27031
27032 public function getDistUrl()
27033 {
27034 return $this->aliasOf->getDistUrl();
27035 }
27036
27037 public function getDistUrls()
27038 {
27039 return $this->aliasOf->getDistUrls();
27040 }
27041
27042 public function getDistReference()
27043 {
27044 return $this->aliasOf->getDistReference();
27045 }
27046
27047 public function setDistReference($reference)
27048 {
27049 return $this->aliasOf->setDistReference($reference);
27050 }
27051
27052 public function getDistSha1Checksum()
27053 {
27054 return $this->aliasOf->getDistSha1Checksum();
27055 }
27056
27057 public function setTransportOptions(array $options)
27058 {
27059 return $this->aliasOf->setTransportOptions($options);
27060 }
27061
27062 public function getTransportOptions()
27063 {
27064 return $this->aliasOf->getTransportOptions();
27065 }
27066
27067 public function setDistMirrors($mirrors)
27068 {
27069 return $this->aliasOf->setDistMirrors($mirrors);
27070 }
27071
27072 public function getDistMirrors()
27073 {
27074 return $this->aliasOf->getDistMirrors();
27075 }
27076
27077 public function getScripts()
27078 {
27079 return $this->aliasOf->getScripts();
27080 }
27081
27082 public function getLicense()
27083 {
27084 return $this->aliasOf->getLicense();
27085 }
27086
27087 public function getAutoload()
27088 {
27089 return $this->aliasOf->getAutoload();
27090 }
27091
27092 public function getDevAutoload()
27093 {
27094 return $this->aliasOf->getDevAutoload();
27095 }
27096
27097 public function getIncludePaths()
27098 {
27099 return $this->aliasOf->getIncludePaths();
27100 }
27101
27102 public function getRepositories()
27103 {
27104 return $this->aliasOf->getRepositories();
27105 }
27106
27107 public function getReleaseDate()
27108 {
27109 return $this->aliasOf->getReleaseDate();
27110 }
27111
27112 public function getBinaries()
27113 {
27114 return $this->aliasOf->getBinaries();
27115 }
27116
27117 public function getKeywords()
27118 {
27119 return $this->aliasOf->getKeywords();
27120 }
27121
27122 public function getDescription()
27123 {
27124 return $this->aliasOf->getDescription();
27125 }
27126
27127 public function getHomepage()
27128 {
27129 return $this->aliasOf->getHomepage();
27130 }
27131
27132 public function getSuggests()
27133 {
27134 return $this->aliasOf->getSuggests();
27135 }
27136
27137 public function getAuthors()
27138 {
27139 return $this->aliasOf->getAuthors();
27140 }
27141
27142 public function getSupport()
27143 {
27144 return $this->aliasOf->getSupport();
27145 }
27146
27147 public function getFunding()
27148 {
27149 return $this->aliasOf->getFunding();
27150 }
27151
27152 public function getNotificationUrl()
27153 {
27154 return $this->aliasOf->getNotificationUrl();
27155 }
27156
27157 public function getArchiveExcludes()
27158 {
27159 return $this->aliasOf->getArchiveExcludes();
27160 }
27161
27162 public function isAbandoned()
27163 {
27164 return $this->aliasOf->isAbandoned();
27165 }
27166
27167 public function getReplacementPackage()
27168 {
27169 return $this->aliasOf->getReplacementPackage();
27170 }
27171
27172 public function __toString()
27173 {
27174 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
27175 }
27176
27177 public function setDistUrl($url)
27178 {
27179 return $this->aliasOf->setDistUrl($url);
27180 }
27181
27182 public function setDistType($type)
27183 {
27184 return $this->aliasOf->setDistType($type);
27185 }
27186 }
27187 <?php
27188
27189
27190
27191
27192
27193
27194
27195
27196
27197
27198
27199 namespace Composer\Package\Archiver;
27200
27201 use FilterIterator;
27202 use PharData;
27203
27204 class ArchivableFilesFilter extends FilterIterator
27205 {
27206 private $dirs = array();
27207
27208
27209
27210
27211 public function accept()
27212 {
27213 $file = $this->getInnerIterator()->current();
27214 if ($file->isDir()) {
27215 $this->dirs[] = (string) $file;
27216
27217 return false;
27218 }
27219
27220 return true;
27221 }
27222
27223 public function addEmptyDir(PharData $phar, $sources)
27224 {
27225 foreach ($this->dirs as $filepath) {
27226 $localname = str_replace($sources . "/", '', $filepath);
27227 $phar->addEmptyDir($localname);
27228 }
27229 }
27230 }
27231 <?php
27232
27233
27234
27235
27236
27237
27238
27239
27240
27241
27242
27243 namespace Composer\Package\Archiver;
27244
27245 use Composer\Util\Filesystem;
27246 use FilesystemIterator;
27247 use Symfony\Component\Finder\Finder;
27248 use Symfony\Component\Finder\SplFileInfo;
27249
27250
27251
27252
27253
27254
27255
27256
27257
27258 class ArchivableFilesFinder extends \FilterIterator
27259 {
27260
27261
27262
27263 protected $finder;
27264
27265
27266
27267
27268
27269
27270
27271
27272 public function __construct($sources, array $excludes, $ignoreFilters = false)
27273 {
27274 $fs = new Filesystem();
27275
27276 $sources = $fs->normalizePath(realpath($sources));
27277
27278 if ($ignoreFilters) {
27279 $filters = array();
27280 } else {
27281 $filters = array(
27282 new HgExcludeFilter($sources),
27283 new GitExcludeFilter($sources),
27284 new ComposerExcludeFilter($sources, $excludes),
27285 );
27286 }
27287
27288 $this->finder = new Finder();
27289
27290 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
27291 if ($file->isLink() && strpos($file->getRealPath(), $sources) !== 0) {
27292 return false;
27293 }
27294
27295 $relativePath = preg_replace(
27296 '#^'.preg_quote($sources, '#').'#',
27297 '',
27298 $fs->normalizePath($file->getRealPath())
27299 );
27300
27301 $exclude = false;
27302 foreach ($filters as $filter) {
27303 $exclude = $filter->filter($relativePath, $exclude);
27304 }
27305
27306 return !$exclude;
27307 };
27308
27309 if (method_exists($filter, 'bindTo')) {
27310 $filter = $filter->bindTo(null);
27311 }
27312
27313 $this->finder
27314 ->in($sources)
27315 ->filter($filter)
27316 ->ignoreVCS(true)
27317 ->ignoreDotFiles(false);
27318
27319 parent::__construct($this->finder->getIterator());
27320 }
27321
27322 public function accept()
27323 {
27324
27325 $current = $this->getInnerIterator()->current();
27326
27327 if (!$current->isDir()) {
27328 return true;
27329 }
27330
27331 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
27332
27333 return !$iterator->valid();
27334 }
27335 }
27336 <?php
27337
27338
27339
27340
27341
27342
27343
27344
27345
27346
27347
27348 namespace Composer\Package\Archiver;
27349
27350 use Composer\Downloader\DownloadManager;
27351 use Composer\Package\PackageInterface;
27352 use Composer\Package\RootPackageInterface;
27353 use Composer\Util\Filesystem;
27354 use Composer\Json\JsonFile;
27355
27356
27357
27358
27359
27360 class ArchiveManager
27361 {
27362 protected $downloadManager;
27363
27364 protected $archivers = array();
27365
27366
27367
27368
27369 protected $overwriteFiles = true;
27370
27371
27372
27373
27374 public function __construct(DownloadManager $downloadManager)
27375 {
27376 $this->downloadManager = $downloadManager;
27377 }
27378
27379
27380
27381
27382 public function addArchiver(ArchiverInterface $archiver)
27383 {
27384 $this->archivers[] = $archiver;
27385 }
27386
27387
27388
27389
27390
27391
27392
27393
27394 public function setOverwriteFiles($overwriteFiles)
27395 {
27396 $this->overwriteFiles = $overwriteFiles;
27397
27398 return $this;
27399 }
27400
27401
27402
27403
27404
27405
27406
27407
27408 public function getPackageFilename(PackageInterface $package)
27409 {
27410 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
27411
27412 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
27413 array_push($nameParts, $package->getDistReference(), $package->getDistType());
27414 } else {
27415 array_push($nameParts, $package->getPrettyVersion(), $package->getDistReference());
27416 }
27417
27418 if ($package->getSourceReference()) {
27419 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
27420 }
27421
27422 $name = implode('-', array_filter($nameParts, function ($p) {
27423 return !empty($p);
27424 }));
27425
27426 return str_replace('/', '-', $name);
27427 }
27428
27429
27430
27431
27432
27433
27434
27435
27436
27437
27438
27439
27440
27441
27442 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
27443 {
27444 if (empty($format)) {
27445 throw new \InvalidArgumentException('Format must be specified');
27446 }
27447
27448
27449 $usableArchiver = null;
27450 foreach ($this->archivers as $archiver) {
27451 if ($archiver->supports($format, $package->getSourceType())) {
27452 $usableArchiver = $archiver;
27453 break;
27454 }
27455 }
27456
27457
27458 if (null === $usableArchiver) {
27459 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
27460 }
27461
27462 $filesystem = new Filesystem();
27463 if (null === $fileName) {
27464 $packageName = $this->getPackageFilename($package);
27465 } else {
27466 $packageName = $fileName;
27467 }
27468
27469
27470 $filesystem->ensureDirectoryExists($targetDir);
27471 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
27472 $filesystem->ensureDirectoryExists(dirname($target));
27473
27474 if (!$this->overwriteFiles && file_exists($target)) {
27475 return $target;
27476 }
27477
27478 if ($package instanceof RootPackageInterface) {
27479 $sourcePath = realpath('.');
27480 } else {
27481
27482 $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
27483 $filesystem->ensureDirectoryExists($sourcePath);
27484
27485 try {
27486
27487 $this->downloadManager->download($package, $sourcePath);
27488 } catch (\Exception $e) {
27489 $filesystem->removeDirectory($sourcePath);
27490 throw $e;
27491 }
27492
27493
27494 if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
27495 $jsonFile = new JsonFile($composerJsonPath);
27496 $jsonData = $jsonFile->read();
27497 if (!empty($jsonData['archive']['exclude'])) {
27498 $package->setArchiveExcludes($jsonData['archive']['exclude']);
27499 }
27500 }
27501 }
27502
27503
27504 $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
27505 $filesystem->ensureDirectoryExists(dirname($tempTarget));
27506
27507 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
27508 $filesystem->rename($archivePath, $target);
27509
27510
27511 if (!$package instanceof RootPackageInterface) {
27512 $filesystem->removeDirectory($sourcePath);
27513 }
27514 $filesystem->remove($tempTarget);
27515
27516 return $target;
27517 }
27518 }
27519 <?php
27520
27521
27522
27523
27524
27525
27526
27527
27528
27529
27530
27531 namespace Composer\Package\Archiver;
27532
27533
27534
27535
27536
27537
27538 interface ArchiverInterface
27539 {
27540
27541
27542
27543
27544
27545
27546
27547
27548
27549
27550 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
27551
27552
27553
27554
27555
27556
27557
27558
27559
27560 public function supports($format, $sourceType);
27561 }
27562 <?php
27563
27564
27565
27566
27567
27568
27569
27570
27571
27572
27573
27574 namespace Composer\Package\Archiver;
27575
27576 use Symfony\Component\Finder;
27577
27578
27579
27580
27581 abstract class BaseExcludeFilter
27582 {
27583
27584
27585
27586 protected $sourcePath;
27587
27588
27589
27590
27591 protected $excludePatterns;
27592
27593
27594
27595
27596 public function __construct($sourcePath)
27597 {
27598 $this->sourcePath = $sourcePath;
27599 $this->excludePatterns = array();
27600 }
27601
27602
27603
27604
27605
27606
27607
27608
27609
27610
27611
27612 public function filter($relativePath, $exclude)
27613 {
27614 foreach ($this->excludePatterns as $patternData) {
27615 list($pattern, $negate, $stripLeadingSlash) = $patternData;
27616
27617 if ($stripLeadingSlash) {
27618 $path = substr($relativePath, 1);
27619 } else {
27620 $path = $relativePath;
27621 }
27622
27623 if (@preg_match($pattern, $path)) {
27624 $exclude = !$negate;
27625 }
27626 }
27627
27628 return $exclude;
27629 }
27630
27631
27632
27633
27634
27635
27636
27637
27638
27639 protected function parseLines(array $lines, $lineParser)
27640 {
27641 return array_filter(
27642 array_map(
27643 function ($line) use ($lineParser) {
27644 $line = trim($line);
27645
27646 if (!$line || 0 === strpos($line, '#')) {
27647 return null;
27648 }
27649
27650 return call_user_func($lineParser, $line);
27651 },
27652 $lines
27653 ),
27654 function ($pattern) {
27655 return $pattern !== null;
27656 }
27657 );
27658 }
27659
27660
27661
27662
27663
27664
27665
27666
27667 protected function generatePatterns($rules)
27668 {
27669 $patterns = array();
27670 foreach ($rules as $rule) {
27671 $patterns[] = $this->generatePattern($rule);
27672 }
27673
27674 return $patterns;
27675 }
27676
27677
27678
27679
27680
27681
27682
27683
27684 protected function generatePattern($rule)
27685 {
27686 $negate = false;
27687 $pattern = '{';
27688
27689 if (strlen($rule) && $rule[0] === '!') {
27690 $negate = true;
27691 $rule = substr($rule, 1);
27692 }
27693
27694 if (strlen($rule) && $rule[0] === '/') {
27695 $pattern .= '^/';
27696 $rule = substr($rule, 1);
27697 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
27698 $pattern .= '/';
27699 $rule = substr($rule, 0, -1);
27700 } elseif (false === strpos($rule, '/')) {
27701 $pattern .= '/';
27702 }
27703
27704
27705 $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
27706
27707 return array($pattern . '}', $negate, false);
27708 }
27709 }
27710 <?php
27711
27712
27713
27714
27715
27716
27717
27718
27719
27720
27721
27722 namespace Composer\Package\Archiver;
27723
27724
27725
27726
27727
27728
27729 class ComposerExcludeFilter extends BaseExcludeFilter
27730 {
27731
27732
27733
27734
27735 public function __construct($sourcePath, array $excludeRules)
27736 {
27737 parent::__construct($sourcePath);
27738 $this->excludePatterns = $this->generatePatterns($excludeRules);
27739 }
27740 }
27741 <?php
27742
27743
27744
27745
27746
27747
27748
27749
27750
27751
27752
27753 namespace Composer\Package\Archiver;
27754
27755
27756
27757
27758
27759
27760
27761
27762 class GitExcludeFilter extends BaseExcludeFilter
27763 {
27764
27765
27766
27767
27768
27769 public function __construct($sourcePath)
27770 {
27771 parent::__construct($sourcePath);
27772
27773 if (file_exists($sourcePath.'/.gitignore')) {
27774 $this->excludePatterns = $this->parseLines(
27775 file($sourcePath.'/.gitignore'),
27776 array($this, 'parseGitIgnoreLine')
27777 );
27778 }
27779 if (file_exists($sourcePath.'/.gitattributes')) {
27780 $this->excludePatterns = array_merge(
27781 $this->excludePatterns,
27782 $this->parseLines(
27783 file($sourcePath.'/.gitattributes'),
27784 array($this, 'parseGitAttributesLine')
27785 )
27786 );
27787 }
27788 }
27789
27790
27791
27792
27793
27794
27795
27796
27797 public function parseGitIgnoreLine($line)
27798 {
27799 return $this->generatePattern($line);
27800 }
27801
27802
27803
27804
27805
27806
27807
27808
27809 public function parseGitAttributesLine($line)
27810 {
27811 $parts = preg_split('#\s+#', $line);
27812
27813 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
27814 return $this->generatePattern($parts[0]);
27815 }
27816
27817 return null;
27818 }
27819 }
27820 <?php
27821
27822
27823
27824
27825
27826
27827
27828
27829
27830
27831
27832 namespace Composer\Package\Archiver;
27833
27834 use Symfony\Component\Finder;
27835
27836
27837
27838
27839
27840
27841 class HgExcludeFilter extends BaseExcludeFilter
27842 {
27843 const HG_IGNORE_REGEX = 1;
27844 const HG_IGNORE_GLOB = 2;
27845
27846
27847
27848
27849
27850 protected $patternMode;
27851
27852
27853
27854
27855
27856
27857 public function __construct($sourcePath)
27858 {
27859 parent::__construct($sourcePath);
27860
27861 $this->patternMode = self::HG_IGNORE_REGEX;
27862
27863 if (file_exists($sourcePath.'/.hgignore')) {
27864 $this->excludePatterns = $this->parseLines(
27865 file($sourcePath.'/.hgignore'),
27866 array($this, 'parseHgIgnoreLine')
27867 );
27868 }
27869 }
27870
27871
27872
27873
27874
27875
27876
27877
27878 public function parseHgIgnoreLine($line)
27879 {
27880 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
27881 if ($matches[1] === 'glob') {
27882 $this->patternMode = self::HG_IGNORE_GLOB;
27883 } else {
27884 $this->patternMode = self::HG_IGNORE_REGEX;
27885 }
27886
27887 return null;
27888 }
27889
27890 if ($this->patternMode == self::HG_IGNORE_GLOB) {
27891 return $this->patternFromGlob($line);
27892 }
27893
27894 return $this->patternFromRegex($line);
27895 }
27896
27897
27898
27899
27900
27901
27902
27903
27904 protected function patternFromGlob($line)
27905 {
27906 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
27907 $pattern = str_replace('[^/]*', '.*', $pattern);
27908
27909 return array($pattern, false, true);
27910 }
27911
27912
27913
27914
27915
27916
27917
27918
27919 public function patternFromRegex($line)
27920 {
27921
27922 $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
27923
27924 return array($pattern, false, true);
27925 }
27926 }
27927 <?php
27928
27929
27930
27931
27932
27933
27934
27935
27936
27937
27938
27939 namespace Composer\Package\Archiver;
27940
27941
27942
27943
27944
27945
27946 class PharArchiver implements ArchiverInterface
27947 {
27948 protected static $formats = array(
27949 'zip' => \Phar::ZIP,
27950 'tar' => \Phar::TAR,
27951 'tar.gz' => \Phar::TAR,
27952 'tar.bz2' => \Phar::TAR,
27953 );
27954
27955 protected static $compressFormats = array(
27956 'tar.gz' => \Phar::GZ,
27957 'tar.bz2' => \Phar::BZ2,
27958 );
27959
27960
27961
27962
27963 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
27964 {
27965 $sources = realpath($sources);
27966
27967
27968 if (file_exists($target)) {
27969 unlink($target);
27970 }
27971
27972 try {
27973 $filename = substr($target, 0, strrpos($target, $format) - 1);
27974
27975
27976 if (isset(static::$compressFormats[$format])) {
27977
27978 $target = $filename . '.tar';
27979 }
27980
27981 $phar = new \PharData($target, null, null, static::$formats[$format]);
27982 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
27983 $filesOnly = new ArchivableFilesFilter($files);
27984 $phar->buildFromIterator($filesOnly, $sources);
27985 $filesOnly->addEmptyDir($phar, $sources);
27986
27987 if (isset(static::$compressFormats[$format])) {
27988
27989 if (!$phar->canCompress(static::$compressFormats[$format])) {
27990 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
27991 }
27992
27993
27994 unlink($target);
27995
27996
27997 $phar->compress(static::$compressFormats[$format]);
27998
27999
28000 $target = $filename . '.' . $format;
28001 }
28002
28003 return $target;
28004 } catch (\UnexpectedValueException $e) {
28005 $message = sprintf(
28006 "Could not create archive '%s' from '%s': %s",
28007 $target,
28008 $sources,
28009 $e->getMessage()
28010 );
28011
28012 throw new \RuntimeException($message, $e->getCode(), $e);
28013 }
28014 }
28015
28016
28017
28018
28019 public function supports($format, $sourceType)
28020 {
28021 return isset(static::$formats[$format]);
28022 }
28023 }
28024 <?php
28025
28026
28027
28028
28029
28030
28031
28032
28033
28034
28035
28036 namespace Composer\Package\Archiver;
28037
28038 use ZipArchive;
28039 use Composer\Util\Filesystem;
28040
28041
28042
28043
28044 class ZipArchiver implements ArchiverInterface
28045 {
28046 protected static $formats = array(
28047 'zip' => 1,
28048 );
28049
28050
28051
28052
28053 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
28054 {
28055 $fs = new Filesystem();
28056 $sources = $fs->normalizePath($sources);
28057
28058 $zip = new ZipArchive();
28059 $res = $zip->open($target, ZipArchive::CREATE);
28060 if ($res === true) {
28061 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
28062 foreach ($files as $file) {
28063
28064 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
28065 $localname = str_replace($sources.'/', '', $filepath);
28066 if ($file->isDir()) {
28067 $zip->addEmptyDir($localname);
28068 } else {
28069 $zip->addFile($filepath, $localname);
28070 }
28071
28072
28073
28074
28075 if (PHP_VERSION_ID >= 50600) {
28076 $perms = fileperms($filepath);
28077
28078
28079
28080
28081 $zip->setExternalAttributesName($localname, ZipArchive::OPSYS_UNIX, $perms << 16);
28082 }
28083 }
28084 if ($zip->close()) {
28085 return $target;
28086 }
28087 }
28088 $message = sprintf(
28089 "Could not create archive '%s' from '%s': %s",
28090 $target,
28091 $sources,
28092 $zip->getStatusString()
28093 );
28094 throw new \RuntimeException($message);
28095 }
28096
28097
28098
28099
28100 public function supports($format, $sourceType)
28101 {
28102 return isset(static::$formats[$format]) && $this->compressionAvailable();
28103 }
28104
28105 private function compressionAvailable()
28106 {
28107 return class_exists('ZipArchive');
28108 }
28109 }
28110 <?php
28111
28112
28113
28114
28115
28116
28117
28118
28119
28120
28121
28122 namespace Composer\Package;
28123
28124 use Composer\Repository\RepositoryInterface;
28125 use Composer\Repository\PlatformRepository;
28126
28127
28128
28129
28130
28131
28132 abstract class BasePackage implements PackageInterface
28133 {
28134 public static $supportedLinkTypes = array(
28135 'require' => array('description' => 'requires', 'method' => 'requires'),
28136 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
28137 'provide' => array('description' => 'provides', 'method' => 'provides'),
28138 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
28139 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
28140 );
28141
28142 const STABILITY_STABLE = 0;
28143 const STABILITY_RC = 5;
28144 const STABILITY_BETA = 10;
28145 const STABILITY_ALPHA = 15;
28146 const STABILITY_DEV = 20;
28147
28148 public static $stabilities = array(
28149 'stable' => self::STABILITY_STABLE,
28150 'RC' => self::STABILITY_RC,
28151 'beta' => self::STABILITY_BETA,
28152 'alpha' => self::STABILITY_ALPHA,
28153 'dev' => self::STABILITY_DEV,
28154 );
28155
28156
28157
28158
28159
28160 public $id;
28161
28162 protected $name;
28163
28164 protected $prettyName;
28165
28166 protected $repository;
28167
28168 protected $transportOptions = array();
28169
28170
28171
28172
28173
28174
28175 public function __construct($name)
28176 {
28177 $this->prettyName = $name;
28178 $this->name = strtolower($name);
28179 $this->id = -1;
28180 }
28181
28182
28183
28184
28185 public function getName()
28186 {
28187 return $this->name;
28188 }
28189
28190
28191
28192
28193 public function getPrettyName()
28194 {
28195 return $this->prettyName;
28196 }
28197
28198
28199
28200
28201 public function getNames()
28202 {
28203 $names = array(
28204 $this->getName() => true,
28205 );
28206
28207 foreach ($this->getProvides() as $link) {
28208 $names[$link->getTarget()] = true;
28209 }
28210
28211 foreach ($this->getReplaces() as $link) {
28212 $names[$link->getTarget()] = true;
28213 }
28214
28215 return array_keys($names);
28216 }
28217
28218
28219
28220
28221 public function setId($id)
28222 {
28223 $this->id = $id;
28224 }
28225
28226
28227
28228
28229 public function getId()
28230 {
28231 return $this->id;
28232 }
28233
28234
28235
28236
28237 public function setRepository(RepositoryInterface $repository)
28238 {
28239 if ($this->repository && $repository !== $this->repository) {
28240 throw new \LogicException('A package can only be added to one repository');
28241 }
28242 $this->repository = $repository;
28243 }
28244
28245
28246
28247
28248 public function getRepository()
28249 {
28250 return $this->repository;
28251 }
28252
28253
28254
28255
28256 public function getTransportOptions()
28257 {
28258 return $this->transportOptions;
28259 }
28260
28261
28262
28263
28264
28265
28266 public function setTransportOptions(array $options)
28267 {
28268 $this->transportOptions = $options;
28269 }
28270
28271
28272
28273
28274
28275
28276 public function isPlatform()
28277 {
28278 return $this->getRepository() instanceof PlatformRepository;
28279 }
28280
28281
28282
28283
28284
28285
28286 public function getUniqueName()
28287 {
28288 return $this->getName().'-'.$this->getVersion();
28289 }
28290
28291 public function equals(PackageInterface $package)
28292 {
28293 $self = $this;
28294 if ($this instanceof AliasPackage) {
28295 $self = $this->getAliasOf();
28296 }
28297 if ($package instanceof AliasPackage) {
28298 $package = $package->getAliasOf();
28299 }
28300
28301 return $package === $self;
28302 }
28303
28304
28305
28306
28307
28308
28309 public function __toString()
28310 {
28311 return $this->getUniqueName();
28312 }
28313
28314 public function getPrettyString()
28315 {
28316 return $this->getPrettyName().' '.$this->getPrettyVersion();
28317 }
28318
28319
28320
28321
28322 public function getFullPrettyVersion($truncate = true)
28323 {
28324 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
28325 return $this->getPrettyVersion();
28326 }
28327
28328
28329 if ($truncate && strlen($this->getSourceReference()) === 40) {
28330 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
28331 }
28332
28333 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
28334 }
28335
28336 public function getStabilityPriority()
28337 {
28338 return self::$stabilities[$this->getStability()];
28339 }
28340
28341 public function __clone()
28342 {
28343 $this->repository = null;
28344 $this->id = -1;
28345 }
28346
28347
28348
28349
28350
28351
28352
28353
28354 public static function packageNameToRegexp($allowListPattern, $wrap = '{^%s$}i')
28355 {
28356 $cleanedAllowListPattern = str_replace('\\*', '.*', preg_quote($allowListPattern));
28357
28358 return sprintf($wrap, $cleanedAllowListPattern);
28359 }
28360 }
28361 <?php
28362
28363
28364
28365
28366
28367
28368
28369
28370
28371
28372
28373 namespace Composer\Package\Comparer;
28374
28375
28376
28377
28378
28379
28380 class Comparer
28381 {
28382 private $source;
28383 private $update;
28384 private $changed;
28385
28386 public function setSource($source)
28387 {
28388 $this->source = $source;
28389 }
28390
28391 public function setUpdate($update)
28392 {
28393 $this->update = $update;
28394 }
28395
28396 public function getChanged($toString = false, $explicated = false)
28397 {
28398 $changed = $this->changed;
28399 if (!count($changed)) {
28400 return false;
28401 }
28402 if ($explicated) {
28403 foreach ($changed as $sectionKey => $itemSection) {
28404 foreach ($itemSection as $itemKey => $item) {
28405 $changed[$sectionKey][$itemKey] = $item.' ('.$sectionKey.')';
28406 }
28407 }
28408 }
28409
28410 if ($toString) {
28411 foreach ($changed as $sectionKey => $itemSection) {
28412 foreach ($itemSection as $itemKey => $item) {
28413 $changed['string'][] = $item."\r\n";
28414 }
28415 }
28416 $changed = implode("\r\n", $changed['string']);
28417 }
28418
28419 return $changed;
28420 }
28421
28422 public function doCompare()
28423 {
28424 $source = array();
28425 $destination = array();
28426 $this->changed = array();
28427 $currentDirectory = getcwd();
28428 chdir($this->source);
28429 $source = $this->doTree('.', $source);
28430 if (!is_array($source)) {
28431 return;
28432 }
28433 chdir($currentDirectory);
28434 chdir($this->update);
28435 $destination = $this->doTree('.', $destination);
28436 if (!is_array($destination)) {
28437 exit;
28438 }
28439 chdir($currentDirectory);
28440 foreach ($source as $dir => $value) {
28441 foreach ($value as $file => $hash) {
28442 if (isset($destination[$dir][$file])) {
28443 if ($hash !== $destination[$dir][$file]) {
28444 $this->changed['changed'][] = $dir.'/'.$file;
28445 }
28446 } else {
28447 $this->changed['removed'][] = $dir.'/'.$file;
28448 }
28449 }
28450 }
28451 foreach ($destination as $dir => $value) {
28452 foreach ($value as $file => $hash) {
28453 if (!isset($source[$dir][$file])) {
28454 $this->changed['added'][] = $dir.'/'.$file;
28455 }
28456 }
28457 }
28458 }
28459
28460 private function doTree($dir, &$array)
28461 {
28462 if ($dh = opendir($dir)) {
28463 while ($file = readdir($dh)) {
28464 if ($file !== '.' && $file !== '..') {
28465 if (is_link($dir.'/'.$file)) {
28466 $array[$dir][$file] = readlink($dir.'/'.$file);
28467 } elseif (is_dir($dir.'/'.$file)) {
28468 if (!count($array)) {
28469 $array[0] = 'Temp';
28470 }
28471 if (!$this->doTree($dir.'/'.$file, $array)) {
28472 return false;
28473 }
28474 } elseif (is_file($dir.'/'.$file) && filesize($dir.'/'.$file)) {
28475 set_time_limit(30);
28476 $array[$dir][$file] = md5_file($dir.'/'.$file);
28477 }
28478 }
28479 }
28480 if (count($array) > 1 && isset($array['0'])) {
28481 unset($array['0']);
28482 }
28483
28484 return $array;
28485 }
28486
28487 return false;
28488 }
28489 }
28490 <?php
28491
28492
28493
28494
28495
28496
28497
28498
28499
28500
28501
28502 namespace Composer\Package;
28503
28504
28505
28506
28507
28508
28509 class CompletePackage extends Package implements CompletePackageInterface
28510 {
28511 protected $repositories;
28512 protected $license = array();
28513 protected $keywords;
28514 protected $authors;
28515 protected $description;
28516 protected $homepage;
28517 protected $scripts = array();
28518 protected $support = array();
28519 protected $funding = array();
28520 protected $abandoned = false;
28521
28522
28523
28524
28525 public function setScripts(array $scripts)
28526 {
28527 $this->scripts = $scripts;
28528 }
28529
28530
28531
28532
28533 public function getScripts()
28534 {
28535 return $this->scripts;
28536 }
28537
28538
28539
28540
28541
28542
28543 public function setRepositories($repositories)
28544 {
28545 $this->repositories = $repositories;
28546 }
28547
28548
28549
28550
28551 public function getRepositories()
28552 {
28553 return $this->repositories;
28554 }
28555
28556
28557
28558
28559
28560
28561 public function setLicense(array $license)
28562 {
28563 $this->license = $license;
28564 }
28565
28566
28567
28568
28569 public function getLicense()
28570 {
28571 return $this->license;
28572 }
28573
28574
28575
28576
28577
28578
28579 public function setKeywords(array $keywords)
28580 {
28581 $this->keywords = $keywords;
28582 }
28583
28584
28585
28586
28587 public function getKeywords()
28588 {
28589 return $this->keywords;
28590 }
28591
28592
28593
28594
28595
28596
28597 public function setAuthors(array $authors)
28598 {
28599 $this->authors = $authors;
28600 }
28601
28602
28603
28604
28605 public function getAuthors()
28606 {
28607 return $this->authors;
28608 }
28609
28610
28611
28612
28613
28614
28615 public function setDescription($description)
28616 {
28617 $this->description = $description;
28618 }
28619
28620
28621
28622
28623 public function getDescription()
28624 {
28625 return $this->description;
28626 }
28627
28628
28629
28630
28631
28632
28633 public function setHomepage($homepage)
28634 {
28635 $this->homepage = $homepage;
28636 }
28637
28638
28639
28640
28641 public function getHomepage()
28642 {
28643 return $this->homepage;
28644 }
28645
28646
28647
28648
28649
28650
28651 public function setSupport(array $support)
28652 {
28653 $this->support = $support;
28654 }
28655
28656
28657
28658
28659 public function getSupport()
28660 {
28661 return $this->support;
28662 }
28663
28664
28665
28666
28667
28668
28669 public function setFunding(array $funding)
28670 {
28671 $this->funding = $funding;
28672 }
28673
28674
28675
28676
28677 public function getFunding()
28678 {
28679 return $this->funding;
28680 }
28681
28682
28683
28684
28685 public function isAbandoned()
28686 {
28687 return (bool) $this->abandoned;
28688 }
28689
28690
28691
28692
28693 public function setAbandoned($abandoned)
28694 {
28695 $this->abandoned = $abandoned;
28696 }
28697
28698
28699
28700
28701
28702
28703 public function getReplacementPackage()
28704 {
28705 return is_string($this->abandoned) ? $this->abandoned : null;
28706 }
28707 }
28708 <?php
28709
28710
28711
28712
28713
28714
28715
28716
28717
28718
28719
28720 namespace Composer\Package;
28721
28722
28723
28724
28725
28726
28727 interface CompletePackageInterface extends PackageInterface
28728 {
28729
28730
28731
28732
28733
28734 public function getScripts();
28735
28736
28737
28738
28739
28740
28741
28742
28743 public function getRepositories();
28744
28745
28746
28747
28748
28749
28750 public function getLicense();
28751
28752
28753
28754
28755
28756
28757 public function getKeywords();
28758
28759
28760
28761
28762
28763
28764 public function getDescription();
28765
28766
28767
28768
28769
28770
28771 public function getHomepage();
28772
28773
28774
28775
28776
28777
28778
28779
28780 public function getAuthors();
28781
28782
28783
28784
28785
28786
28787 public function getSupport();
28788
28789
28790
28791
28792
28793
28794
28795
28796 public function getFunding();
28797
28798
28799
28800
28801
28802
28803 public function isAbandoned();
28804
28805
28806
28807
28808
28809
28810 public function getReplacementPackage();
28811 }
28812 <?php
28813
28814
28815
28816
28817
28818
28819
28820
28821
28822
28823
28824 namespace Composer\Package\Dumper;
28825
28826 use Composer\Package\BasePackage;
28827 use Composer\Package\PackageInterface;
28828 use Composer\Package\CompletePackageInterface;
28829 use Composer\Package\RootPackageInterface;
28830
28831
28832
28833
28834
28835 class ArrayDumper
28836 {
28837 public function dump(PackageInterface $package)
28838 {
28839 $keys = array(
28840 'binaries' => 'bin',
28841 'type',
28842 'extra',
28843 'installationSource' => 'installation-source',
28844 'autoload',
28845 'devAutoload' => 'autoload-dev',
28846 'notificationUrl' => 'notification-url',
28847 'includePaths' => 'include-path',
28848 );
28849
28850 $data = array();
28851 $data['name'] = $package->getPrettyName();
28852 $data['version'] = $package->getPrettyVersion();
28853 $data['version_normalized'] = $package->getVersion();
28854
28855 if ($package->getTargetDir()) {
28856 $data['target-dir'] = $package->getTargetDir();
28857 }
28858
28859 if ($package->getSourceType()) {
28860 $data['source']['type'] = $package->getSourceType();
28861 $data['source']['url'] = $package->getSourceUrl();
28862 if (null !== ($value = $package->getSourceReference())) {
28863 $data['source']['reference'] = $value;
28864 }
28865 if ($mirrors = $package->getSourceMirrors()) {
28866 $data['source']['mirrors'] = $mirrors;
28867 }
28868 }
28869
28870 if ($package->getDistType()) {
28871 $data['dist']['type'] = $package->getDistType();
28872 $data['dist']['url'] = $package->getDistUrl();
28873 if (null !== ($value = $package->getDistReference())) {
28874 $data['dist']['reference'] = $value;
28875 }
28876 if (null !== ($value = $package->getDistSha1Checksum())) {
28877 $data['dist']['shasum'] = $value;
28878 }
28879 if ($mirrors = $package->getDistMirrors()) {
28880 $data['dist']['mirrors'] = $mirrors;
28881 }
28882 }
28883
28884 if ($package->getArchiveExcludes()) {
28885 $data['archive']['exclude'] = $package->getArchiveExcludes();
28886 }
28887
28888 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
28889 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
28890 foreach ($links as $link) {
28891 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
28892 }
28893 ksort($data[$type]);
28894 }
28895 }
28896
28897 if ($packages = $package->getSuggests()) {
28898 ksort($packages);
28899 $data['suggest'] = $packages;
28900 }
28901
28902 if ($package->getReleaseDate()) {
28903 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
28904 }
28905
28906 $data = $this->dumpValues($package, $keys, $data);
28907
28908 if ($package instanceof CompletePackageInterface) {
28909 $keys = array(
28910 'scripts',
28911 'license',
28912 'authors',
28913 'description',
28914 'homepage',
28915 'keywords',
28916 'repositories',
28917 'support',
28918 'funding',
28919 );
28920
28921 $data = $this->dumpValues($package, $keys, $data);
28922
28923 if (isset($data['keywords']) && is_array($data['keywords'])) {
28924 sort($data['keywords']);
28925 }
28926
28927 if ($package->isAbandoned()) {
28928 $data['abandoned'] = $package->getReplacementPackage() ?: true;
28929 }
28930 }
28931
28932 if ($package instanceof RootPackageInterface) {
28933 $minimumStability = $package->getMinimumStability();
28934 if ($minimumStability) {
28935 $data['minimum-stability'] = $minimumStability;
28936 }
28937 }
28938
28939 if (count($package->getTransportOptions()) > 0) {
28940 $data['transport-options'] = $package->getTransportOptions();
28941 }
28942
28943 return $data;
28944 }
28945
28946 private function dumpValues(PackageInterface $package, array $keys, array $data)
28947 {
28948 foreach ($keys as $method => $key) {
28949 if (is_numeric($method)) {
28950 $method = $key;
28951 }
28952
28953 $getter = 'get'.ucfirst($method);
28954 $value = $package->$getter();
28955
28956 if (null !== $value && !(is_array($value) && 0 === count($value))) {
28957 $data[$key] = $value;
28958 }
28959 }
28960
28961 return $data;
28962 }
28963 }
28964 <?php
28965
28966
28967
28968
28969
28970
28971
28972
28973
28974
28975
28976 namespace Composer\Package;
28977
28978 use Composer\Semver\Constraint\ConstraintInterface;
28979
28980
28981
28982
28983
28984
28985 class Link
28986 {
28987
28988
28989
28990 protected $source;
28991
28992
28993
28994
28995 protected $target;
28996
28997
28998
28999
29000 protected $constraint;
29001
29002
29003
29004
29005 protected $description;
29006
29007
29008
29009
29010 protected $prettyConstraint;
29011
29012
29013
29014
29015
29016
29017
29018
29019
29020
29021 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
29022 {
29023 $this->source = strtolower($source);
29024 $this->target = strtolower($target);
29025 $this->constraint = $constraint;
29026 $this->description = $description;
29027 $this->prettyConstraint = $prettyConstraint;
29028 }
29029
29030
29031
29032
29033 public function getDescription()
29034 {
29035 return $this->description;
29036 }
29037
29038
29039
29040
29041 public function getSource()
29042 {
29043 return $this->source;
29044 }
29045
29046
29047
29048
29049 public function getTarget()
29050 {
29051 return $this->target;
29052 }
29053
29054
29055
29056
29057 public function getConstraint()
29058 {
29059 return $this->constraint;
29060 }
29061
29062
29063
29064
29065
29066 public function getPrettyConstraint()
29067 {
29068 if (null === $this->prettyConstraint) {
29069 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
29070 }
29071
29072 return $this->prettyConstraint;
29073 }
29074
29075
29076
29077
29078 public function __toString()
29079 {
29080 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
29081 }
29082
29083
29084
29085
29086
29087 public function getPrettyString(PackageInterface $sourcePackage)
29088 {
29089 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
29090 }
29091 }
29092 <?php
29093
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104 namespace Composer\Package\LinkConstraint;
29105
29106 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
29107
29108 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
29109
29110
29111
29112
29113 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
29114 {
29115 }
29116 <?php
29117
29118
29119
29120
29121
29122
29123
29124
29125
29126
29127
29128 namespace Composer\Package\LinkConstraint;
29129
29130 use Composer\Semver\Constraint\ConstraintInterface;
29131
29132 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
29133
29134
29135
29136
29137 interface LinkConstraintInterface extends ConstraintInterface
29138 {
29139 }
29140 <?php
29141
29142
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152 namespace Composer\Package\LinkConstraint;
29153
29154 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
29155
29156 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
29157
29158
29159
29160
29161 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
29162 {
29163 }
29164 <?php
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174
29175
29176 namespace Composer\Package\LinkConstraint;
29177
29178 use Composer\Semver\Constraint\AbstractConstraint;
29179
29180 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
29181
29182
29183
29184
29185 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
29186 {
29187 }
29188 <?php
29189
29190
29191
29192
29193
29194
29195
29196
29197
29198
29199
29200 namespace Composer\Package\LinkConstraint;
29201
29202 use Composer\Semver\Constraint\Constraint;
29203
29204 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
29205
29206
29207
29208
29209 class VersionConstraint extends Constraint implements LinkConstraintInterface
29210 {
29211 }
29212 <?php
29213
29214
29215
29216
29217
29218
29219
29220
29221
29222
29223
29224 namespace Composer\Package\Loader;
29225
29226 use Composer\Package;
29227 use Composer\Package\AliasPackage;
29228 use Composer\Package\Link;
29229 use Composer\Package\RootAliasPackage;
29230 use Composer\Package\RootPackageInterface;
29231 use Composer\Package\Version\VersionParser;
29232 use Composer\Semver\VersionParser as SemverVersionParser;
29233
29234
29235
29236
29237
29238 class ArrayLoader implements LoaderInterface
29239 {
29240 protected $versionParser;
29241 protected $loadOptions;
29242
29243 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
29244 {
29245 if (!$parser) {
29246 $parser = new VersionParser;
29247 }
29248 $this->versionParser = $parser;
29249 $this->loadOptions = $loadOptions;
29250 }
29251
29252 public function load(array $config, $class = 'Composer\Package\CompletePackage')
29253 {
29254 if (!isset($config['name'])) {
29255 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
29256 }
29257 if (!isset($config['version'])) {
29258 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
29259 }
29260
29261
29262 if (isset($config['version_normalized'])) {
29263 $version = $config['version_normalized'];
29264 } else {
29265 $version = $this->versionParser->normalize($config['version']);
29266 }
29267 $package = new $class($config['name'], $version, $config['version']);
29268 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
29269
29270 if (isset($config['target-dir'])) {
29271 $package->setTargetDir($config['target-dir']);
29272 }
29273
29274 if (isset($config['extra']) && is_array($config['extra'])) {
29275 $package->setExtra($config['extra']);
29276 }
29277
29278 if (isset($config['bin'])) {
29279 if (!\is_array($config['bin'])) {
29280 $config['bin'] = array($config['bin']);
29281 }
29282 foreach ($config['bin'] as $key => $bin) {
29283 $config['bin'][$key] = ltrim($bin, '/');
29284 }
29285 $package->setBinaries($config['bin']);
29286 }
29287
29288 if (isset($config['installation-source'])) {
29289 $package->setInstallationSource($config['installation-source']);
29290 }
29291
29292 if (isset($config['source'])) {
29293 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
29294 throw new \UnexpectedValueException(sprintf(
29295 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
29296 $config['name'],
29297 json_encode($config['source'])
29298 ));
29299 }
29300 $package->setSourceType($config['source']['type']);
29301 $package->setSourceUrl($config['source']['url']);
29302 $package->setSourceReference(isset($config['source']['reference']) ? $config['source']['reference'] : null);
29303 if (isset($config['source']['mirrors'])) {
29304 $package->setSourceMirrors($config['source']['mirrors']);
29305 }
29306 }
29307
29308 if (isset($config['dist'])) {
29309 if (!isset($config['dist']['type'])
29310 || !isset($config['dist']['url'])) {
29311 throw new \UnexpectedValueException(sprintf(
29312 "Package %s's dist key should be specified as ".
29313 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
29314 $config['name'],
29315 json_encode($config['dist'])
29316 ));
29317 }
29318 $package->setDistType($config['dist']['type']);
29319 $package->setDistUrl($config['dist']['url']);
29320 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
29321 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
29322 if (isset($config['dist']['mirrors'])) {
29323 $package->setDistMirrors($config['dist']['mirrors']);
29324 }
29325 }
29326
29327 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
29328 if (isset($config[$type])) {
29329 $method = 'set'.ucfirst($opts['method']);
29330 $package->{$method}(
29331 $this->parseLinks(
29332 $package->getName(),
29333 $package->getPrettyVersion(),
29334 $opts['description'],
29335 $config[$type]
29336 )
29337 );
29338 }
29339 }
29340
29341 if (isset($config['suggest']) && is_array($config['suggest'])) {
29342 foreach ($config['suggest'] as $target => $reason) {
29343 if ('self.version' === trim($reason)) {
29344 $config['suggest'][$target] = $package->getPrettyVersion();
29345 }
29346 }
29347 $package->setSuggests($config['suggest']);
29348 }
29349
29350 if (isset($config['autoload'])) {
29351 $package->setAutoload($config['autoload']);
29352 }
29353
29354 if (isset($config['autoload-dev'])) {
29355 $package->setDevAutoload($config['autoload-dev']);
29356 }
29357
29358 if (isset($config['include-path'])) {
29359 $package->setIncludePaths($config['include-path']);
29360 }
29361
29362 if (!empty($config['time'])) {
29363 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
29364
29365 try {
29366 $date = new \DateTime($time, new \DateTimeZone('UTC'));
29367 $package->setReleaseDate($date);
29368 } catch (\Exception $e) {
29369 }
29370 }
29371
29372 if (!empty($config['notification-url'])) {
29373 $package->setNotificationUrl($config['notification-url']);
29374 }
29375
29376 if (!empty($config['archive']['exclude'])) {
29377 $package->setArchiveExcludes($config['archive']['exclude']);
29378 }
29379
29380 if ($package instanceof Package\CompletePackageInterface) {
29381 if (isset($config['scripts']) && is_array($config['scripts'])) {
29382 foreach ($config['scripts'] as $event => $listeners) {
29383 $config['scripts'][$event] = (array) $listeners;
29384 }
29385 if (isset($config['scripts']['composer'])) {
29386 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
29387 }
29388 $package->setScripts($config['scripts']);
29389 }
29390
29391 if (!empty($config['description']) && is_string($config['description'])) {
29392 $package->setDescription($config['description']);
29393 }
29394
29395 if (!empty($config['homepage']) && is_string($config['homepage'])) {
29396 $package->setHomepage($config['homepage']);
29397 }
29398
29399 if (!empty($config['keywords']) && is_array($config['keywords'])) {
29400 $package->setKeywords($config['keywords']);
29401 }
29402
29403 if (!empty($config['license'])) {
29404 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
29405 }
29406
29407 if (!empty($config['authors']) && is_array($config['authors'])) {
29408 $package->setAuthors($config['authors']);
29409 }
29410
29411 if (isset($config['support'])) {
29412 $package->setSupport($config['support']);
29413 }
29414
29415 if (!empty($config['funding']) && is_array($config['funding'])) {
29416 $package->setFunding($config['funding']);
29417 }
29418
29419 if (isset($config['abandoned'])) {
29420 $package->setAbandoned($config['abandoned']);
29421 }
29422 }
29423
29424 if ($aliasNormalized = $this->getBranchAlias($config)) {
29425 if ($package instanceof RootPackageInterface) {
29426 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
29427 } else {
29428 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
29429 }
29430 }
29431
29432 if ($this->loadOptions && isset($config['transport-options'])) {
29433 $package->setTransportOptions($config['transport-options']);
29434 }
29435
29436 return $package;
29437 }
29438
29439
29440
29441
29442
29443
29444
29445
29446 public function parseLinks($source, $sourceVersion, $description, $links)
29447 {
29448 $res = array();
29449 foreach ($links as $target => $constraint) {
29450 if (!is_string($constraint)) {
29451 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
29452 }
29453 if ('self.version' === $constraint) {
29454 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
29455 } else {
29456 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
29457 }
29458
29459 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
29460 }
29461
29462 return $res;
29463 }
29464
29465
29466
29467
29468
29469
29470
29471 public function getBranchAlias(array $config)
29472 {
29473 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
29474 || !isset($config['extra']['branch-alias'])
29475 || !is_array($config['extra']['branch-alias'])
29476 ) {
29477 return;
29478 }
29479
29480 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
29481
29482 if ('-dev' !== substr($targetBranch, -4)) {
29483 continue;
29484 }
29485
29486
29487 $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
29488 if ('-dev' !== substr($validatedTargetBranch, -4)) {
29489 continue;
29490 }
29491
29492
29493 if (strtolower($config['version']) !== strtolower($sourceBranch)) {
29494 continue;
29495 }
29496
29497
29498 if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
29499 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
29500 && (stripos($targetPrefix, $sourcePrefix) !== 0)
29501 ) {
29502 continue;
29503 }
29504
29505 return $validatedTargetBranch;
29506 }
29507 }
29508 }
29509 <?php
29510
29511
29512
29513
29514
29515
29516
29517
29518
29519
29520
29521 namespace Composer\Package\Loader;
29522
29523
29524
29525
29526 class InvalidPackageException extends \Exception
29527 {
29528 private $errors;
29529 private $warnings;
29530 private $data;
29531
29532 public function __construct(array $errors, array $warnings, array $data)
29533 {
29534 $this->errors = $errors;
29535 $this->warnings = $warnings;
29536 $this->data = $data;
29537 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
29538 }
29539
29540 public function getData()
29541 {
29542 return $this->data;
29543 }
29544
29545 public function getErrors()
29546 {
29547 return $this->errors;
29548 }
29549
29550 public function getWarnings()
29551 {
29552 return $this->warnings;
29553 }
29554 }
29555 <?php
29556
29557
29558
29559
29560
29561
29562
29563
29564
29565
29566
29567 namespace Composer\Package\Loader;
29568
29569 use Composer\Json\JsonFile;
29570
29571
29572
29573
29574 class JsonLoader
29575 {
29576 private $loader;
29577
29578 public function __construct(LoaderInterface $loader)
29579 {
29580 $this->loader = $loader;
29581 }
29582
29583
29584
29585
29586
29587 public function load($json)
29588 {
29589 if ($json instanceof JsonFile) {
29590 $config = $json->read();
29591 } elseif (file_exists($json)) {
29592 $config = JsonFile::parseJson(file_get_contents($json), $json);
29593 } elseif (is_string($json)) {
29594 $config = JsonFile::parseJson($json);
29595 }
29596
29597 return $this->loader->load($config);
29598 }
29599 }
29600 <?php
29601
29602
29603
29604
29605
29606
29607
29608
29609
29610
29611
29612 namespace Composer\Package\Loader;
29613
29614
29615
29616
29617
29618
29619 interface LoaderInterface
29620 {
29621
29622
29623
29624
29625
29626
29627
29628 public function load(array $package, $class = 'Composer\Package\CompletePackage');
29629 }
29630 <?php
29631
29632
29633
29634
29635
29636
29637
29638
29639
29640
29641
29642 namespace Composer\Package\Loader;
29643
29644 use Composer\Package\BasePackage;
29645 use Composer\Package\AliasPackage;
29646 use Composer\Config;
29647 use Composer\IO\IOInterface;
29648 use Composer\Package\RootPackageInterface;
29649 use Composer\Repository\RepositoryFactory;
29650 use Composer\Package\Version\VersionGuesser;
29651 use Composer\Package\Version\VersionParser;
29652 use Composer\Repository\RepositoryManager;
29653 use Composer\Util\ProcessExecutor;
29654
29655
29656
29657
29658
29659
29660
29661
29662 class RootPackageLoader extends ArrayLoader
29663 {
29664
29665
29666
29667 private $manager;
29668
29669
29670
29671
29672 private $config;
29673
29674
29675
29676
29677 private $versionGuesser;
29678
29679
29680
29681
29682 private $io;
29683
29684 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null, IOInterface $io = null)
29685 {
29686 parent::__construct($parser);
29687
29688 $this->manager = $manager;
29689 $this->config = $config;
29690 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
29691 $this->io = $io;
29692 }
29693
29694
29695
29696
29697
29698
29699
29700 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
29701 {
29702 if (!isset($config['name'])) {
29703 $config['name'] = '__root__';
29704 } elseif ($this->io) {
29705 if ($err = ValidatingArrayLoader::hasPackageNamingError($config['name'])) {
29706 $this->io->writeError('<warning>Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
29707 }
29708 }
29709 $autoVersioned = false;
29710 if (!isset($config['version'])) {
29711 $commit = null;
29712
29713
29714 if (getenv('COMPOSER_ROOT_VERSION')) {
29715 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
29716 } else {
29717 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
29718 if ($versionData) {
29719 $config['version'] = $versionData['pretty_version'];
29720 $config['version_normalized'] = $versionData['version'];
29721 $commit = $versionData['commit'];
29722 }
29723 }
29724
29725 if (!isset($config['version'])) {
29726 $config['version'] = '1.0.0';
29727 $autoVersioned = true;
29728 }
29729
29730 if ($commit) {
29731 $config['source'] = array(
29732 'type' => '',
29733 'url' => '',
29734 'reference' => $commit,
29735 );
29736 $config['dist'] = array(
29737 'type' => '',
29738 'url' => '',
29739 'reference' => $commit,
29740 );
29741 }
29742 }
29743
29744 $realPackage = $package = parent::load($config, $class);
29745 if ($realPackage instanceof AliasPackage) {
29746 $realPackage = $package->getAliasOf();
29747 }
29748
29749 if ($autoVersioned) {
29750 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
29751 }
29752
29753 if (isset($config['minimum-stability'])) {
29754 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
29755 }
29756
29757 $aliases = array();
29758 $stabilityFlags = array();
29759 $references = array();
29760 foreach (array('require', 'require-dev') as $linkType) {
29761 if (isset($config[$linkType])) {
29762 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
29763 $method = 'get'.ucfirst($linkInfo['method']);
29764 $links = array();
29765 foreach ($realPackage->$method() as $link) {
29766 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
29767 }
29768 $aliases = $this->extractAliases($links, $aliases);
29769 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
29770 $references = $this->extractReferences($links, $references);
29771
29772 if (isset($links[$config['name']])) {
29773 throw new \RuntimeException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
29774 'Did you accidentally name your root package after an external package?', $config['name']));
29775 }
29776 }
29777 }
29778
29779 if ($this->io) {
29780 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
29781 if (isset($config[$linkType])) {
29782 foreach ($config[$linkType] as $linkName => $constraint) {
29783 if ($err = ValidatingArrayLoader::hasPackageNamingError($linkName, true)) {
29784 $this->io->writeError('<warning>Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
29785 }
29786 }
29787 }
29788 }
29789 }
29790
29791 $realPackage->setAliases($aliases);
29792 $realPackage->setStabilityFlags($stabilityFlags);
29793 $realPackage->setReferences($references);
29794
29795 if (isset($config['prefer-stable'])) {
29796 $realPackage->setPreferStable((bool) $config['prefer-stable']);
29797 }
29798
29799 if (isset($config['config'])) {
29800 $realPackage->setConfig($config['config']);
29801 }
29802
29803 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
29804 foreach ($repos as $repo) {
29805 $this->manager->addRepository($repo);
29806 }
29807 $realPackage->setRepositories($this->config->getRepositories());
29808
29809 return $package;
29810 }
29811
29812 private function extractAliases(array $requires, array $aliases)
29813 {
29814 foreach ($requires as $reqName => $reqVersion) {
29815 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
29816 $aliases[] = array(
29817 'package' => strtolower($reqName),
29818 'version' => $this->versionParser->normalize($match[1], $reqVersion),
29819 'alias' => $match[2],
29820 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
29821 );
29822 } elseif (strpos($reqVersion, ' as ') !== false) {
29823 throw new \UnexpectedValueException('Invalid alias definition in "'.$reqName.'": "'.$reqVersion.'". Aliases should be in the form "exact-version as other-exact-version".');
29824 }
29825 }
29826
29827 return $aliases;
29828 }
29829
29830 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
29831 {
29832 $stabilities = BasePackage::$stabilities;
29833 $minimumStability = $stabilities[$minimumStability];
29834 foreach ($requires as $reqName => $reqVersion) {
29835 $constraints = array();
29836
29837
29838 $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
29839 foreach ($orSplit as $orConstraint) {
29840 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
29841 foreach ($andSplit as $andConstraint) {
29842 $constraints[] = $andConstraint;
29843 }
29844 }
29845
29846
29847 $match = false;
29848 foreach ($constraints as $constraint) {
29849 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
29850 $name = strtolower($reqName);
29851 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
29852
29853 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
29854 continue;
29855 }
29856 $stabilityFlags[$name] = $stability;
29857 $match = true;
29858 }
29859 }
29860
29861 if ($match) {
29862 continue;
29863 }
29864
29865 foreach ($constraints as $constraint) {
29866
29867
29868 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
29869 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
29870 $name = strtolower($reqName);
29871 $stability = $stabilities[$stabilityName];
29872 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
29873 continue;
29874 }
29875 $stabilityFlags[$name] = $stability;
29876 }
29877 }
29878 }
29879
29880 return $stabilityFlags;
29881 }
29882
29883 private function extractReferences(array $requires, array $references)
29884 {
29885 foreach ($requires as $reqName => $reqVersion) {
29886 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
29887 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) {
29888 $name = strtolower($reqName);
29889 $references[$name] = $match[1];
29890 }
29891 }
29892
29893 return $references;
29894 }
29895 }
29896 <?php
29897
29898
29899
29900
29901
29902
29903
29904
29905
29906
29907
29908 namespace Composer\Package\Loader;
29909
29910 use Composer\Package\BasePackage;
29911 use Composer\Semver\Constraint\Constraint;
29912 use Composer\Package\Version\VersionParser;
29913 use Composer\Repository\PlatformRepository;
29914 use Composer\Spdx\SpdxLicenses;
29915
29916
29917
29918
29919 class ValidatingArrayLoader implements LoaderInterface
29920 {
29921 const CHECK_ALL = 3;
29922 const CHECK_UNBOUND_CONSTRAINTS = 1;
29923 const CHECK_STRICT_CONSTRAINTS = 2;
29924
29925 private $loader;
29926 private $versionParser;
29927 private $errors;
29928 private $warnings;
29929 private $config;
29930 private $strictName;
29931 private $flags;
29932
29933 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
29934 {
29935 $this->loader = $loader;
29936 $this->versionParser = $parser ?: new VersionParser();
29937 $this->strictName = $strictName;
29938 $this->flags = $flags;
29939 }
29940
29941 public function load(array $config, $class = 'Composer\Package\CompletePackage')
29942 {
29943 $this->errors = array();
29944 $this->warnings = array();
29945 $this->config = $config;
29946
29947 if ($err = self::hasPackageNamingError($config['name'])) {
29948 $this->warnings[] = 'Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.';
29949 }
29950
29951 if ($this->strictName) {
29952 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
29953 } else {
29954 $this->validateString('name', true);
29955 }
29956
29957 if (!empty($this->config['version'])) {
29958 try {
29959 $this->versionParser->normalize($this->config['version']);
29960 } catch (\Exception $e) {
29961 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
29962 unset($this->config['version']);
29963 }
29964 }
29965
29966 if (!empty($this->config['config']['platform'])) {
29967 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
29968 try {
29969 $this->versionParser->normalize($platform);
29970 } catch (\Exception $e) {
29971 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
29972 }
29973 }
29974 }
29975
29976 $this->validateRegex('type', '[A-Za-z0-9-]+');
29977 $this->validateString('target-dir');
29978 $this->validateArray('extra');
29979
29980 if (isset($this->config['bin'])) {
29981 if (is_string($this->config['bin'])) {
29982 $this->validateString('bin');
29983 } else {
29984 $this->validateFlatArray('bin');
29985 }
29986 }
29987
29988 $this->validateArray('scripts'); 
29989 $this->validateString('description');
29990 $this->validateUrl('homepage');
29991 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
29992
29993 $releaseDate = null;
29994 $this->validateString('time');
29995 if (!empty($this->config['time'])) {
29996 try {
29997 $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
29998 } catch (\Exception $e) {
29999 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
30000 unset($this->config['time']);
30001 }
30002 }
30003
30004
30005 if (isset($this->config['license']) && (!$releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days'))) {
30006 if (is_array($this->config['license']) || is_string($this->config['license'])) {
30007 $licenses = (array) $this->config['license'];
30008
30009 $licenseValidator = new SpdxLicenses();
30010 foreach ($licenses as $license) {
30011
30012 if ('proprietary' === $license) {
30013 continue;
30014 }
30015 $licenseToValidate = str_replace('proprietary', 'MIT', $license);
30016 if (!$licenseValidator->validate($licenseToValidate)) {
30017 if ($licenseValidator->validate(trim($licenseToValidate))) {
30018 $this->warnings[] = sprintf(
30019 'License %s must not contain extra spaces, make sure to trim it.',
30020 json_encode($license)
30021 );
30022 } else {
30023 $this->warnings[] = sprintf(
30024 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
30025 'If the software is closed-source, you may use "proprietary" as license.',
30026 json_encode($license)
30027 );
30028 }
30029 }
30030 }
30031 }
30032 }
30033
30034 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
30035 foreach ($this->config['authors'] as $key => $author) {
30036 if (!is_array($author)) {
30037 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
30038 unset($this->config['authors'][$key]);
30039 continue;
30040 }
30041 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
30042 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
30043 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
30044 unset($this->config['authors'][$key][$authorData]);
30045 }
30046 }
30047 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
30048 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
30049 unset($this->config['authors'][$key]['homepage']);
30050 }
30051 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
30052 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
30053 unset($this->config['authors'][$key]['email']);
30054 }
30055 if (empty($this->config['authors'][$key])) {
30056 unset($this->config['authors'][$key]);
30057 }
30058 }
30059 if (empty($this->config['authors'])) {
30060 unset($this->config['authors']);
30061 }
30062 }
30063
30064 if ($this->validateArray('support') && !empty($this->config['support'])) {
30065 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss', 'chat') as $key) {
30066 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
30067 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
30068 unset($this->config['support'][$key]);
30069 }
30070 }
30071
30072 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
30073 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
30074 unset($this->config['support']['email']);
30075 }
30076
30077 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
30078 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
30079 unset($this->config['support']['irc']);
30080 }
30081
30082 foreach (array('issues', 'forum', 'wiki', 'source', 'docs', 'chat') as $key) {
30083 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
30084 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
30085 unset($this->config['support'][$key]);
30086 }
30087 }
30088 if (empty($this->config['support'])) {
30089 unset($this->config['support']);
30090 }
30091 }
30092
30093 if ($this->validateArray('funding') && !empty($this->config['funding'])) {
30094 foreach ($this->config['funding'] as $key => $fundingOption) {
30095 if (!is_array($fundingOption)) {
30096 $this->errors[] = 'funding.'.$key.' : should be an array, '.gettype($fundingOption).' given';
30097 unset($this->config['funding'][$key]);
30098 continue;
30099 }
30100 foreach (array('type', 'url') as $fundingData) {
30101 if (isset($fundingOption[$fundingData]) && !is_string($fundingOption[$fundingData])) {
30102 $this->errors[] = 'funding.'.$key.'.'.$fundingData.' : invalid value, must be a string';
30103 unset($this->config['funding'][$key][$fundingData]);
30104 }
30105 }
30106 if (isset($fundingOption['url']) && !$this->filterUrl($fundingOption['url'])) {
30107 $this->warnings[] = 'funding.'.$key.'.url : invalid value ('.$fundingOption['url'].'), must be an http/https URL';
30108 unset($this->config['funding'][$key]['url']);
30109 }
30110 if (empty($this->config['funding'][$key])) {
30111 unset($this->config['funding'][$key]);
30112 }
30113 }
30114 if (empty($this->config['funding'])) {
30115 unset($this->config['funding']);
30116 }
30117 }
30118
30119 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
30120 $stableConstraint = new Constraint('=', '1.0.0');
30121
30122 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
30123 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
30124 foreach ($this->config[$linkType] as $package => $constraint) {
30125 if ($err = self::hasPackageNamingError($package, true)) {
30126 $this->warnings[] = 'Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.';
30127 } elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
30128 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
30129 }
30130 if (!is_string($constraint)) {
30131 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
30132 unset($this->config[$linkType][$package]);
30133 } elseif ('self.version' !== $constraint) {
30134 try {
30135 $linkConstraint = $this->versionParser->parseConstraints($constraint);
30136 } catch (\Exception $e) {
30137 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
30138 unset($this->config[$linkType][$package]);
30139 continue;
30140 }
30141
30142
30143 if (
30144 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
30145 && 'require' === $linkType
30146 && $linkConstraint->matches($unboundConstraint)
30147 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
30148 ) {
30149 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
30150 } elseif (
30151
30152 ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
30153 && 'require' === $linkType
30154 && substr($linkConstraint, 0, 1) === '='
30155 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
30156 ) {
30157 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
30158 }
30159 }
30160 }
30161 }
30162 }
30163
30164 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
30165 foreach ($this->config['suggest'] as $package => $description) {
30166 if (!is_string($description)) {
30167 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
30168 unset($this->config['suggest'][$package]);
30169 }
30170 }
30171 }
30172
30173 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
30174 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
30175 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
30176 unset($this->config['minimum-stability']);
30177 }
30178 }
30179
30180 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
30181 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
30182 foreach ($this->config['autoload'] as $type => $typeConfig) {
30183 if (!in_array($type, $types)) {
30184 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
30185 unset($this->config['autoload'][$type]);
30186 }
30187 if ($type === 'psr-4') {
30188 foreach ($typeConfig as $namespace => $dirs) {
30189 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
30190 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
30191 }
30192 }
30193 }
30194 }
30195 }
30196
30197 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
30198 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
30199
30200
30201 unset($this->config['autoload']['psr-4']);
30202 }
30203
30204
30205
30206
30207
30208
30209
30210 $this->validateFlatArray('include-path');
30211 $this->validateArray('transport-options');
30212
30213
30214 if (isset($this->config['extra']['branch-alias'])) {
30215 if (!is_array($this->config['extra']['branch-alias'])) {
30216 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
30217 } else {
30218 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
30219
30220 if ('-dev' !== substr($targetBranch, -4)) {
30221 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
30222 unset($this->config['extra']['branch-alias'][$sourceBranch]);
30223
30224 continue;
30225 }
30226
30227
30228 $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
30229 if ('-dev' !== substr($validatedTargetBranch, -4)) {
30230 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
30231 unset($this->config['extra']['branch-alias'][$sourceBranch]);
30232
30233 continue;
30234 }
30235
30236
30237 if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
30238 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
30239 && (stripos($targetPrefix, $sourcePrefix) !== 0)
30240 ) {
30241 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
30242 unset($this->config['extra']['branch-alias'][$sourceBranch]);
30243 }
30244 }
30245 }
30246 }
30247
30248 if ($this->errors) {
30249 throw new InvalidPackageException($this->errors, $this->warnings, $config);
30250 }
30251
30252 $package = $this->loader->load($this->config, $class);
30253 $this->config = null;
30254
30255 return $package;
30256 }
30257
30258 public function getWarnings()
30259 {
30260 return $this->warnings;
30261 }
30262
30263 public function getErrors()
30264 {
30265 return $this->errors;
30266 }
30267
30268 public static function hasPackageNamingError($name, $isLink = false)
30269 {
30270 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
30271 return;
30272 }
30273
30274 if (!preg_match('{^[a-z0-9](?:[_.-]?[a-z0-9]+)*/[a-z0-9](?:(?:[_.]?|-{0,2})[a-z0-9]+)*$}iD', $name)) {
30275 return $name.' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".';
30276 }
30277
30278 $reservedNames = array('nul', 'con', 'prn', 'aux', 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9', 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9');
30279 $bits = explode('/', strtolower($name));
30280 if (in_array($bits[0], $reservedNames, true) || in_array($bits[1], $reservedNames, true)) {
30281 return $name.' is reserved, package and vendor names can not match any of: '.implode(', ', $reservedNames).'.';
30282 }
30283
30284 if (preg_match('{\.json$}', $name)) {
30285 return $name.' is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.';
30286 }
30287
30288 if (preg_match('{[A-Z]}', $name)) {
30289 if ($isLink) {
30290 return $name.' is invalid, it should not contain uppercase characters. Please use '.strtolower($name).' instead.';
30291 }
30292
30293 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
30294 $suggestName = strtolower($suggestName);
30295
30296 return $name.' is invalid, it should not contain uppercase characters. We suggest using '.$suggestName.' instead.';
30297 }
30298 }
30299
30300 private function validateRegex($property, $regex, $mandatory = false)
30301 {
30302 if (!$this->validateString($property, $mandatory)) {
30303 return false;
30304 }
30305
30306 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
30307 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
30308 if ($mandatory) {
30309 $this->errors[] = $message;
30310 } else {
30311 $this->warnings[] = $message;
30312 }
30313 unset($this->config[$property]);
30314
30315 return false;
30316 }
30317
30318 return true;
30319 }
30320
30321 private function validateString($property, $mandatory = false)
30322 {
30323 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
30324 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
30325 unset($this->config[$property]);
30326
30327 return false;
30328 }
30329
30330 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
30331 if ($mandatory) {
30332 $this->errors[] = $property.' : must be present';
30333 }
30334 unset($this->config[$property]);
30335
30336 return false;
30337 }
30338
30339 return true;
30340 }
30341
30342 private function validateArray($property, $mandatory = false)
30343 {
30344 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
30345 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
30346 unset($this->config[$property]);
30347
30348 return false;
30349 }
30350
30351 if (!isset($this->config[$property]) || !count($this->config[$property])) {
30352 if ($mandatory) {
30353 $this->errors[] = $property.' : must be present and contain at least one element';
30354 }
30355 unset($this->config[$property]);
30356
30357 return false;
30358 }
30359
30360 return true;
30361 }
30362
30363 private function validateFlatArray($property, $regex = null, $mandatory = false)
30364 {
30365 if (!$this->validateArray($property, $mandatory)) {
30366 return false;
30367 }
30368
30369 $pass = true;
30370 foreach ($this->config[$property] as $key => $value) {
30371 if (!is_string($value) && !is_numeric($value)) {
30372 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
30373 unset($this->config[$property][$key]);
30374 $pass = false;
30375
30376 continue;
30377 }
30378
30379 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
30380 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
30381 unset($this->config[$property][$key]);
30382 $pass = false;
30383 }
30384 }
30385
30386 return $pass;
30387 }
30388
30389 private function validateUrl($property, $mandatory = false)
30390 {
30391 if (!$this->validateString($property, $mandatory)) {
30392 return false;
30393 }
30394
30395 if (!$this->filterUrl($this->config[$property])) {
30396 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
30397 unset($this->config[$property]);
30398
30399 return false;
30400 }
30401
30402 return true;
30403 }
30404
30405 private function filterUrl($value, array $schemes = array('http', 'https'))
30406 {
30407 if ($value === '') {
30408 return true;
30409 }
30410
30411 $bits = parse_url($value);
30412 if (empty($bits['scheme']) || empty($bits['host'])) {
30413 return false;
30414 }
30415
30416 if (!in_array($bits['scheme'], $schemes, true)) {
30417 return false;
30418 }
30419
30420 return true;
30421 }
30422 }
30423 <?php
30424
30425
30426
30427
30428
30429
30430
30431
30432
30433
30434
30435 namespace Composer\Package;
30436
30437 use Composer\Json\JsonFile;
30438 use Composer\Installer\InstallationManager;
30439 use Composer\Repository\RepositoryManager;
30440 use Composer\Util\ProcessExecutor;
30441 use Composer\Repository\ArrayRepository;
30442 use Composer\Package\Dumper\ArrayDumper;
30443 use Composer\Package\Loader\ArrayLoader;
30444 use Composer\Plugin\PluginInterface;
30445 use Composer\Util\Git as GitUtil;
30446 use Composer\IO\IOInterface;
30447 use Seld\JsonLint\ParsingException;
30448
30449
30450
30451
30452
30453
30454
30455 class Locker
30456 {
30457 private $lockFile;
30458 private $repositoryManager;
30459 private $installationManager;
30460 private $hash;
30461 private $contentHash;
30462 private $loader;
30463 private $dumper;
30464 private $process;
30465 private $lockDataCache;
30466
30467
30468
30469
30470
30471
30472
30473
30474
30475
30476 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
30477 {
30478 $this->lockFile = $lockFile;
30479 $this->repositoryManager = $repositoryManager;
30480 $this->installationManager = $installationManager;
30481 $this->hash = md5($composerFileContents);
30482 $this->contentHash = self::getContentHash($composerFileContents);
30483 $this->loader = new ArrayLoader(null, true);
30484 $this->dumper = new ArrayDumper();
30485 $this->process = new ProcessExecutor($io);
30486 }
30487
30488
30489
30490
30491
30492
30493
30494
30495 public static function getContentHash($composerFileContents)
30496 {
30497 $content = json_decode($composerFileContents, true);
30498
30499 $relevantKeys = array(
30500 'name',
30501 'version',
30502 'require',
30503 'require-dev',
30504 'conflict',
30505 'replace',
30506 'provide',
30507 'minimum-stability',
30508 'prefer-stable',
30509 'repositories',
30510 'extra',
30511 );
30512
30513 $relevantContent = array();
30514
30515 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
30516 $relevantContent[$key] = $content[$key];
30517 }
30518 if (isset($content['config']['platform'])) {
30519 $relevantContent['config']['platform'] = $content['config']['platform'];
30520 }
30521
30522 ksort($relevantContent);
30523
30524 return md5(json_encode($relevantContent));
30525 }
30526
30527
30528
30529
30530
30531
30532 public function isLocked()
30533 {
30534 if (!$this->lockFile->exists()) {
30535 return false;
30536 }
30537
30538 $data = $this->getLockData();
30539
30540 return isset($data['packages']);
30541 }
30542
30543
30544
30545
30546
30547
30548 public function isFresh()
30549 {
30550 $lock = $this->lockFile->read();
30551
30552 if (!empty($lock['content-hash'])) {
30553
30554 return $this->contentHash === $lock['content-hash'];
30555 }
30556
30557
30558 if (!empty($lock['hash'])) {
30559 return $this->hash === $lock['hash'];
30560 }
30561
30562
30563 return false;
30564 }
30565
30566
30567
30568
30569
30570
30571
30572
30573 public function getLockedRepository($withDevReqs = false)
30574 {
30575 $lockData = $this->getLockData();
30576 $packages = new ArrayRepository();
30577
30578 $lockedPackages = $lockData['packages'];
30579 if ($withDevReqs) {
30580 if (isset($lockData['packages-dev'])) {
30581 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
30582 } else {
30583 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.');
30584 }
30585 }
30586
30587 if (empty($lockedPackages)) {
30588 return $packages;
30589 }
30590
30591 if (isset($lockedPackages[0]['name'])) {
30592 foreach ($lockedPackages as $info) {
30593 $packages->addPackage($this->loader->load($info));
30594 }
30595
30596 return $packages;
30597 }
30598
30599 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.');
30600 }
30601
30602
30603
30604
30605
30606
30607
30608 public function getPlatformRequirements($withDevReqs = false)
30609 {
30610 $lockData = $this->getLockData();
30611 $requirements = array();
30612
30613 if (!empty($lockData['platform'])) {
30614 $requirements = $this->loader->parseLinks(
30615 '__ROOT__',
30616 '1.0.0',
30617 'requires',
30618 isset($lockData['platform']) ? $lockData['platform'] : array()
30619 );
30620 }
30621
30622 if ($withDevReqs && !empty($lockData['platform-dev'])) {
30623 $devRequirements = $this->loader->parseLinks(
30624 '__ROOT__',
30625 '1.0.0',
30626 'requires',
30627 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
30628 );
30629
30630 $requirements = array_merge($requirements, $devRequirements);
30631 }
30632
30633 return $requirements;
30634 }
30635
30636 public function getMinimumStability()
30637 {
30638 $lockData = $this->getLockData();
30639
30640 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
30641 }
30642
30643 public function getStabilityFlags()
30644 {
30645 $lockData = $this->getLockData();
30646
30647 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
30648 }
30649
30650 public function getPreferStable()
30651 {
30652 $lockData = $this->getLockData();
30653
30654
30655
30656 return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
30657 }
30658
30659 public function getPreferLowest()
30660 {
30661 $lockData = $this->getLockData();
30662
30663
30664
30665 return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
30666 }
30667
30668 public function getPlatformOverrides()
30669 {
30670 $lockData = $this->getLockData();
30671
30672 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
30673 }
30674
30675 public function getAliases()
30676 {
30677 $lockData = $this->getLockData();
30678
30679 if (!isset($lockData['aliases'])) {
30680 return array();
30681 }
30682
30683
30684
30685 foreach ($lockData['aliases'] as $index => $alias) {
30686 if (in_array($alias['version'], array('dev-master', 'dev-default', 'dev-trunk'), true)) {
30687 $lockData['aliases'][$index]['version'] = '9999999-dev';
30688 }
30689 }
30690
30691 return $lockData['aliases'];
30692 }
30693
30694 public function getLockData()
30695 {
30696 if (null !== $this->lockDataCache) {
30697 return $this->lockDataCache;
30698 }
30699
30700 if (!$this->lockFile->exists()) {
30701 throw new \LogicException('No lockfile found. Unable to read locked packages');
30702 }
30703
30704 return $this->lockDataCache = $this->lockFile->read();
30705 }
30706
30707
30708
30709
30710
30711
30712
30713
30714
30715
30716
30717
30718
30719
30720
30721
30722
30723 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
30724 {
30725 $lock = array(
30726 '_readme' => array('This file locks the dependencies of your project to a known state',
30727 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies',
30728 'This file is @gener'.'ated automatically', ),
30729 'content-hash' => $this->contentHash,
30730 'packages' => null,
30731 'packages-dev' => null,
30732 'aliases' => array(),
30733 'minimum-stability' => $minimumStability,
30734 'stability-flags' => $stabilityFlags,
30735 'prefer-stable' => $preferStable,
30736 'prefer-lowest' => $preferLowest,
30737 );
30738
30739 foreach ($aliases as $package => $versions) {
30740 foreach ($versions as $version => $alias) {
30741 $lock['aliases'][] = array(
30742 'alias' => $alias['alias'],
30743 'alias_normalized' => $alias['alias_normalized'],
30744 'version' => $version,
30745 'package' => $package,
30746 );
30747 }
30748 }
30749
30750 $lock['packages'] = $this->lockPackages($packages);
30751 if (null !== $devPackages) {
30752 $lock['packages-dev'] = $this->lockPackages($devPackages);
30753 }
30754
30755 $lock['platform'] = $platformReqs;
30756 $lock['platform-dev'] = $platformDevReqs;
30757 if ($platformOverrides) {
30758 $lock['platform-overrides'] = $platformOverrides;
30759 }
30760 $lock['plugin-api-version'] = PluginInterface::PLUGIN_API_VERSION;
30761
30762 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
30763 if ($this->lockFile->exists()) {
30764 unlink($this->lockFile->getPath());
30765 }
30766
30767 return false;
30768 }
30769
30770 try {
30771 $isLocked = $this->isLocked();
30772 } catch (ParsingException $e) {
30773 $isLocked = false;
30774 }
30775 if (!$isLocked || $lock !== $this->getLockData()) {
30776 $this->lockFile->write($lock);
30777 $this->lockDataCache = null;
30778
30779 return true;
30780 }
30781
30782 return false;
30783 }
30784
30785 private function lockPackages(array $packages)
30786 {
30787 $locked = array();
30788
30789 foreach ($packages as $package) {
30790 if ($package instanceof AliasPackage) {
30791 continue;
30792 }
30793
30794 $name = $package->getPrettyName();
30795 $version = $package->getPrettyVersion();
30796
30797 if (!$name || !$version) {
30798 throw new \LogicException(sprintf(
30799 'Package "%s" has no version or name and can not be locked',
30800 $package
30801 ));
30802 }
30803
30804 $spec = $this->dumper->dump($package);
30805 unset($spec['version_normalized']);
30806
30807
30808 $time = isset($spec['time']) ? $spec['time'] : null;
30809 unset($spec['time']);
30810 if ($package->isDev() && $package->getInstallationSource() === 'source') {
30811
30812 $time = $this->getPackageTime($package) ?: $time;
30813 }
30814 if (null !== $time) {
30815 $spec['time'] = $time;
30816 }
30817
30818 unset($spec['installation-source']);
30819
30820 $locked[] = $spec;
30821 }
30822
30823 usort($locked, function ($a, $b) {
30824 $comparison = strcmp($a['name'], $b['name']);
30825
30826 if (0 !== $comparison) {
30827 return $comparison;
30828 }
30829
30830
30831 return strcmp($a['version'], $b['version']);
30832 });
30833
30834 return $locked;
30835 }
30836
30837
30838
30839
30840
30841
30842
30843 private function getPackageTime(PackageInterface $package)
30844 {
30845 if (!function_exists('proc_open')) {
30846 return null;
30847 }
30848
30849 $path = realpath($this->installationManager->getInstallPath($package));
30850 $sourceType = $package->getSourceType();
30851 $datetime = null;
30852
30853 if ($path && in_array($sourceType, array('git', 'hg'))) {
30854 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
30855 switch ($sourceType) {
30856 case 'git':
30857 GitUtil::cleanEnv();
30858
30859 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef).GitUtil::getNoShowSignatureFlag($this->process), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
30860 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
30861 }
30862 break;
30863
30864 case 'hg':
30865 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
30866 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
30867 }
30868 break;
30869 }
30870 }
30871
30872 return $datetime ? $datetime->format(DATE_RFC3339) : null;
30873 }
30874 }
30875 <?php
30876
30877
30878
30879
30880
30881
30882
30883
30884
30885
30886
30887 namespace Composer\Package;
30888
30889 use Composer\Package\Version\VersionParser;
30890 use Composer\Util\ComposerMirror;
30891
30892
30893
30894
30895
30896
30897 class Package extends BasePackage
30898 {
30899 protected $type;
30900 protected $targetDir;
30901 protected $installationSource;
30902 protected $sourceType;
30903 protected $sourceUrl;
30904 protected $sourceReference;
30905 protected $sourceMirrors;
30906 protected $distType;
30907 protected $distUrl;
30908 protected $distReference;
30909 protected $distSha1Checksum;
30910 protected $distMirrors;
30911 protected $version;
30912 protected $prettyVersion;
30913 protected $releaseDate;
30914 protected $extra = array();
30915 protected $binaries = array();
30916 protected $dev;
30917 protected $stability;
30918 protected $notificationUrl;
30919
30920
30921 protected $requires = array();
30922
30923 protected $conflicts = array();
30924
30925 protected $provides = array();
30926
30927 protected $replaces = array();
30928
30929 protected $devRequires = array();
30930 protected $suggests = array();
30931 protected $autoload = array();
30932 protected $devAutoload = array();
30933 protected $includePaths = array();
30934 protected $archiveExcludes = array();
30935
30936
30937
30938
30939
30940
30941
30942
30943 public function __construct($name, $version, $prettyVersion)
30944 {
30945 parent::__construct($name);
30946
30947 $this->version = $version;
30948 $this->prettyVersion = $prettyVersion;
30949
30950 $this->stability = VersionParser::parseStability($version);
30951 $this->dev = $this->stability === 'dev';
30952 }
30953
30954
30955
30956
30957 public function isDev()
30958 {
30959 return $this->dev;
30960 }
30961
30962
30963
30964
30965 public function setType($type)
30966 {
30967 $this->type = $type;
30968 }
30969
30970
30971
30972
30973 public function getType()
30974 {
30975 return $this->type ?: 'library';
30976 }
30977
30978
30979
30980
30981 public function getStability()
30982 {
30983 return $this->stability;
30984 }
30985
30986
30987
30988
30989 public function setTargetDir($targetDir)
30990 {
30991 $this->targetDir = $targetDir;
30992 }
30993
30994
30995
30996
30997 public function getTargetDir()
30998 {
30999 if (null === $this->targetDir) {
31000 return;
31001 }
31002
31003 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
31004 }
31005
31006
31007
31008
31009 public function setExtra(array $extra)
31010 {
31011 $this->extra = $extra;
31012 }
31013
31014
31015
31016
31017 public function getExtra()
31018 {
31019 return $this->extra;
31020 }
31021
31022
31023
31024
31025 public function setBinaries(array $binaries)
31026 {
31027 $this->binaries = $binaries;
31028 }
31029
31030
31031
31032
31033 public function getBinaries()
31034 {
31035 return $this->binaries;
31036 }
31037
31038
31039
31040
31041 public function setInstallationSource($type)
31042 {
31043 $this->installationSource = $type;
31044 }
31045
31046
31047
31048
31049 public function getInstallationSource()
31050 {
31051 return $this->installationSource;
31052 }
31053
31054
31055
31056
31057 public function setSourceType($type)
31058 {
31059 $this->sourceType = $type;
31060 }
31061
31062
31063
31064
31065 public function getSourceType()
31066 {
31067 return $this->sourceType;
31068 }
31069
31070
31071
31072
31073 public function setSourceUrl($url)
31074 {
31075 $this->sourceUrl = $url;
31076 }
31077
31078
31079
31080
31081 public function getSourceUrl()
31082 {
31083 return $this->sourceUrl;
31084 }
31085
31086
31087
31088
31089 public function setSourceReference($reference)
31090 {
31091 $this->sourceReference = $reference;
31092 }
31093
31094
31095
31096
31097 public function getSourceReference()
31098 {
31099 return $this->sourceReference;
31100 }
31101
31102
31103
31104
31105 public function setSourceMirrors($mirrors)
31106 {
31107 $this->sourceMirrors = $mirrors;
31108 }
31109
31110
31111
31112
31113 public function getSourceMirrors()
31114 {
31115 return $this->sourceMirrors;
31116 }
31117
31118
31119
31120
31121 public function getSourceUrls()
31122 {
31123 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
31124 }
31125
31126
31127
31128
31129 public function setDistType($type)
31130 {
31131 $this->distType = $type;
31132 }
31133
31134
31135
31136
31137 public function getDistType()
31138 {
31139 return $this->distType;
31140 }
31141
31142
31143
31144
31145 public function setDistUrl($url)
31146 {
31147 $this->distUrl = $url;
31148 }
31149
31150
31151
31152
31153 public function getDistUrl()
31154 {
31155 return $this->distUrl;
31156 }
31157
31158
31159
31160
31161 public function setDistReference($reference)
31162 {
31163 $this->distReference = $reference;
31164 }
31165
31166
31167
31168
31169 public function getDistReference()
31170 {
31171 return $this->distReference;
31172 }
31173
31174
31175
31176
31177 public function setDistSha1Checksum($sha1checksum)
31178 {
31179 $this->distSha1Checksum = $sha1checksum;
31180 }
31181
31182
31183
31184
31185 public function getDistSha1Checksum()
31186 {
31187 return $this->distSha1Checksum;
31188 }
31189
31190
31191
31192
31193 public function setDistMirrors($mirrors)
31194 {
31195 $this->distMirrors = $mirrors;
31196 }
31197
31198
31199
31200
31201 public function getDistMirrors()
31202 {
31203 return $this->distMirrors;
31204 }
31205
31206
31207
31208
31209 public function getDistUrls()
31210 {
31211 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
31212 }
31213
31214
31215
31216
31217 public function getVersion()
31218 {
31219 return $this->version;
31220 }
31221
31222
31223
31224
31225 public function getPrettyVersion()
31226 {
31227 return $this->prettyVersion;
31228 }
31229
31230
31231
31232
31233
31234
31235 public function setReleaseDate(\DateTime $releaseDate)
31236 {
31237 $this->releaseDate = $releaseDate;
31238 }
31239
31240
31241
31242
31243 public function getReleaseDate()
31244 {
31245 return $this->releaseDate;
31246 }
31247
31248
31249
31250
31251
31252
31253 public function setRequires(array $requires)
31254 {
31255 $this->requires = $requires;
31256 }
31257
31258
31259
31260
31261 public function getRequires()
31262 {
31263 return $this->requires;
31264 }
31265
31266
31267
31268
31269
31270
31271 public function setConflicts(array $conflicts)
31272 {
31273 $this->conflicts = $conflicts;
31274 }
31275
31276
31277
31278
31279 public function getConflicts()
31280 {
31281 return $this->conflicts;
31282 }
31283
31284
31285
31286
31287
31288
31289 public function setProvides(array $provides)
31290 {
31291 $this->provides = $provides;
31292 }
31293
31294
31295
31296
31297 public function getProvides()
31298 {
31299 return $this->provides;
31300 }
31301
31302
31303
31304
31305
31306
31307 public function setReplaces(array $replaces)
31308 {
31309 $this->replaces = $replaces;
31310 }
31311
31312
31313
31314
31315 public function getReplaces()
31316 {
31317 return $this->replaces;
31318 }
31319
31320
31321
31322
31323
31324
31325 public function setDevRequires(array $devRequires)
31326 {
31327 $this->devRequires = $devRequires;
31328 }
31329
31330
31331
31332
31333 public function getDevRequires()
31334 {
31335 return $this->devRequires;
31336 }
31337
31338
31339
31340
31341
31342
31343 public function setSuggests(array $suggests)
31344 {
31345 $this->suggests = $suggests;
31346 }
31347
31348
31349
31350
31351 public function getSuggests()
31352 {
31353 return $this->suggests;
31354 }
31355
31356
31357
31358
31359
31360
31361 public function setAutoload(array $autoload)
31362 {
31363 $this->autoload = $autoload;
31364 }
31365
31366
31367
31368
31369 public function getAutoload()
31370 {
31371 return $this->autoload;
31372 }
31373
31374
31375
31376
31377
31378
31379 public function setDevAutoload(array $devAutoload)
31380 {
31381 $this->devAutoload = $devAutoload;
31382 }
31383
31384
31385
31386
31387 public function getDevAutoload()
31388 {
31389 return $this->devAutoload;
31390 }
31391
31392
31393
31394
31395
31396
31397 public function setIncludePaths(array $includePaths)
31398 {
31399 $this->includePaths = $includePaths;
31400 }
31401
31402
31403
31404
31405 public function getIncludePaths()
31406 {
31407 return $this->includePaths;
31408 }
31409
31410
31411
31412
31413
31414
31415 public function setNotificationUrl($notificationUrl)
31416 {
31417 $this->notificationUrl = $notificationUrl;
31418 }
31419
31420
31421
31422
31423 public function getNotificationUrl()
31424 {
31425 return $this->notificationUrl;
31426 }
31427
31428
31429
31430
31431
31432
31433 public function setArchiveExcludes(array $excludes)
31434 {
31435 $this->archiveExcludes = $excludes;
31436 }
31437
31438
31439
31440
31441 public function getArchiveExcludes()
31442 {
31443 return $this->archiveExcludes;
31444 }
31445
31446
31447
31448
31449
31450
31451
31452
31453 public function replaceVersion($version, $prettyVersion)
31454 {
31455 $this->version = $version;
31456 $this->prettyVersion = $prettyVersion;
31457
31458 $this->stability = VersionParser::parseStability($version);
31459 $this->dev = $this->stability === 'dev';
31460 }
31461
31462 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
31463 {
31464 if (!$url) {
31465 return array();
31466 }
31467 $urls = array($url);
31468 if ($mirrors) {
31469 foreach ($mirrors as $mirror) {
31470 if ($urlType === 'dist') {
31471 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
31472 } elseif ($urlType === 'source' && $type === 'git') {
31473 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
31474 } elseif ($urlType === 'source' && $type === 'hg') {
31475 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
31476 }
31477 if (!in_array($mirrorUrl, $urls)) {
31478 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
31479 $func($urls, $mirrorUrl);
31480 }
31481 }
31482 }
31483
31484 return $urls;
31485 }
31486 }
31487 <?php
31488
31489
31490
31491
31492
31493
31494
31495
31496
31497
31498
31499 namespace Composer\Package;
31500
31501 use Composer\Repository\RepositoryInterface;
31502
31503
31504
31505
31506
31507
31508 interface PackageInterface
31509 {
31510
31511
31512
31513
31514
31515 public function getName();
31516
31517
31518
31519
31520
31521
31522 public function getPrettyName();
31523
31524
31525
31526
31527
31528
31529
31530
31531
31532 public function getNames();
31533
31534
31535
31536
31537
31538
31539 public function setId($id);
31540
31541
31542
31543
31544
31545
31546 public function getId();
31547
31548
31549
31550
31551
31552
31553 public function isDev();
31554
31555
31556
31557
31558
31559
31560 public function getType();
31561
31562
31563
31564
31565
31566
31567 public function getTargetDir();
31568
31569
31570
31571
31572
31573
31574 public function getExtra();
31575
31576
31577
31578
31579
31580
31581 public function setInstallationSource($type);
31582
31583
31584
31585
31586
31587
31588 public function getInstallationSource();
31589
31590
31591
31592
31593
31594
31595 public function getSourceType();
31596
31597
31598
31599
31600
31601
31602 public function getSourceUrl();
31603
31604
31605
31606
31607
31608
31609 public function getSourceUrls();
31610
31611
31612
31613
31614
31615
31616 public function getSourceReference();
31617
31618
31619
31620
31621
31622
31623 public function getSourceMirrors();
31624
31625
31626
31627
31628
31629
31630 public function getDistType();
31631
31632
31633
31634
31635
31636
31637 public function getDistUrl();
31638
31639
31640
31641
31642
31643
31644 public function getDistUrls();
31645
31646
31647
31648
31649
31650
31651 public function getDistReference();
31652
31653
31654
31655
31656
31657
31658 public function getDistSha1Checksum();
31659
31660
31661
31662
31663
31664
31665 public function getDistMirrors();
31666
31667
31668
31669
31670
31671
31672 public function getVersion();
31673
31674
31675
31676
31677
31678
31679 public function getPrettyVersion();
31680
31681
31682
31683
31684
31685
31686
31687
31688
31689 public function getFullPrettyVersion($truncate = true);
31690
31691
31692
31693
31694
31695
31696 public function getReleaseDate();
31697
31698
31699
31700
31701
31702
31703 public function getStability();
31704
31705
31706
31707
31708
31709
31710
31711 public function getRequires();
31712
31713
31714
31715
31716
31717
31718
31719 public function getConflicts();
31720
31721
31722
31723
31724
31725
31726
31727 public function getProvides();
31728
31729
31730
31731
31732
31733
31734
31735 public function getReplaces();
31736
31737
31738
31739
31740
31741
31742
31743 public function getDevRequires();
31744
31745
31746
31747
31748
31749
31750
31751 public function getSuggests();
31752
31753
31754
31755
31756
31757
31758
31759
31760
31761
31762
31763 public function getAutoload();
31764
31765
31766
31767
31768
31769
31770
31771
31772
31773
31774
31775 public function getDevAutoload();
31776
31777
31778
31779
31780
31781
31782
31783 public function getIncludePaths();
31784
31785
31786
31787
31788
31789
31790 public function setRepository(RepositoryInterface $repository);
31791
31792
31793
31794
31795
31796
31797 public function getRepository();
31798
31799
31800
31801
31802
31803
31804 public function getBinaries();
31805
31806
31807
31808
31809
31810
31811 public function getUniqueName();
31812
31813
31814
31815
31816
31817
31818 public function getNotificationUrl();
31819
31820
31821
31822
31823
31824
31825 public function __toString();
31826
31827
31828
31829
31830
31831
31832 public function getPrettyString();
31833
31834
31835
31836
31837
31838
31839 public function getArchiveExcludes();
31840
31841
31842
31843
31844
31845
31846 public function getTransportOptions();
31847
31848
31849
31850
31851
31852
31853 public function setSourceReference($reference);
31854
31855
31856
31857
31858
31859
31860 public function setDistUrl($url);
31861
31862
31863
31864
31865
31866
31867 public function setDistType($type);
31868
31869
31870
31871
31872
31873
31874 public function setDistReference($reference);
31875 }
31876 <?php
31877
31878
31879
31880
31881
31882
31883
31884
31885
31886
31887
31888 namespace Composer\Package;
31889
31890
31891
31892
31893 class RootAliasPackage extends AliasPackage implements RootPackageInterface
31894 {
31895 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
31896 {
31897 parent::__construct($aliasOf, $version, $prettyVersion);
31898 }
31899
31900
31901
31902
31903 public function getAliases()
31904 {
31905 return $this->aliasOf->getAliases();
31906 }
31907
31908
31909
31910
31911 public function getMinimumStability()
31912 {
31913 return $this->aliasOf->getMinimumStability();
31914 }
31915
31916
31917
31918
31919 public function getStabilityFlags()
31920 {
31921 return $this->aliasOf->getStabilityFlags();
31922 }
31923
31924
31925
31926
31927 public function getReferences()
31928 {
31929 return $this->aliasOf->getReferences();
31930 }
31931
31932
31933
31934
31935 public function getPreferStable()
31936 {
31937 return $this->aliasOf->getPreferStable();
31938 }
31939
31940
31941
31942
31943 public function getConfig()
31944 {
31945 return $this->aliasOf->getConfig();
31946 }
31947
31948
31949
31950
31951 public function setRequires(array $require)
31952 {
31953 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
31954
31955 $this->aliasOf->setRequires($require);
31956 }
31957
31958
31959
31960
31961 public function setDevRequires(array $devRequire)
31962 {
31963 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
31964
31965 $this->aliasOf->setDevRequires($devRequire);
31966 }
31967
31968
31969
31970
31971 public function setConflicts(array $conflicts)
31972 {
31973 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
31974 $this->aliasOf->setConflicts($conflicts);
31975 }
31976
31977
31978
31979
31980 public function setProvides(array $provides)
31981 {
31982 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
31983 $this->aliasOf->setProvides($provides);
31984 }
31985
31986
31987
31988
31989 public function setReplaces(array $replaces)
31990 {
31991 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
31992 $this->aliasOf->setReplaces($replaces);
31993 }
31994
31995
31996
31997
31998 public function setRepositories($repositories)
31999 {
32000 $this->aliasOf->setRepositories($repositories);
32001 }
32002
32003
32004
32005
32006 public function setAutoload(array $autoload)
32007 {
32008 $this->aliasOf->setAutoload($autoload);
32009 }
32010
32011
32012
32013
32014 public function setDevAutoload(array $devAutoload)
32015 {
32016 $this->aliasOf->setDevAutoload($devAutoload);
32017 }
32018
32019
32020
32021
32022 public function setStabilityFlags(array $stabilityFlags)
32023 {
32024 $this->aliasOf->setStabilityFlags($stabilityFlags);
32025 }
32026
32027
32028
32029
32030 public function setSuggests(array $suggests)
32031 {
32032 $this->aliasOf->setSuggests($suggests);
32033 }
32034
32035
32036
32037
32038 public function setExtra(array $extra)
32039 {
32040 $this->aliasOf->setExtra($extra);
32041 }
32042
32043 public function __clone()
32044 {
32045 parent::__clone();
32046 $this->aliasOf = clone $this->aliasOf;
32047 }
32048 }
32049 <?php
32050
32051
32052
32053
32054
32055
32056
32057
32058
32059
32060
32061 namespace Composer\Package;
32062
32063
32064
32065
32066
32067
32068 class RootPackage extends CompletePackage implements RootPackageInterface
32069 {
32070 protected $minimumStability = 'stable';
32071 protected $preferStable = false;
32072 protected $stabilityFlags = array();
32073 protected $config = array();
32074 protected $references = array();
32075 protected $aliases = array();
32076
32077
32078
32079
32080
32081
32082 public function setMinimumStability($minimumStability)
32083 {
32084 $this->minimumStability = $minimumStability;
32085 }
32086
32087
32088
32089
32090 public function getMinimumStability()
32091 {
32092 return $this->minimumStability;
32093 }
32094
32095
32096
32097
32098
32099
32100 public function setStabilityFlags(array $stabilityFlags)
32101 {
32102 $this->stabilityFlags = $stabilityFlags;
32103 }
32104
32105
32106
32107
32108 public function getStabilityFlags()
32109 {
32110 return $this->stabilityFlags;
32111 }
32112
32113
32114
32115
32116
32117
32118 public function setPreferStable($preferStable)
32119 {
32120 $this->preferStable = $preferStable;
32121 }
32122
32123
32124
32125
32126 public function getPreferStable()
32127 {
32128 return $this->preferStable;
32129 }
32130
32131
32132
32133
32134
32135
32136 public function setConfig(array $config)
32137 {
32138 $this->config = $config;
32139 }
32140
32141
32142
32143
32144 public function getConfig()
32145 {
32146 return $this->config;
32147 }
32148
32149
32150
32151
32152
32153
32154 public function setReferences(array $references)
32155 {
32156 $this->references = $references;
32157 }
32158
32159
32160
32161
32162 public function getReferences()
32163 {
32164 return $this->references;
32165 }
32166
32167
32168
32169
32170
32171
32172 public function setAliases(array $aliases)
32173 {
32174 $this->aliases = $aliases;
32175 }
32176
32177
32178
32179
32180 public function getAliases()
32181 {
32182 return $this->aliases;
32183 }
32184 }
32185 <?php
32186
32187
32188
32189
32190
32191
32192
32193
32194
32195
32196
32197 namespace Composer\Package;
32198
32199
32200
32201
32202
32203
32204 interface RootPackageInterface extends CompletePackageInterface
32205 {
32206
32207
32208
32209
32210
32211 public function getAliases();
32212
32213
32214
32215
32216
32217
32218 public function getMinimumStability();
32219
32220
32221
32222
32223
32224
32225
32226
32227 public function getStabilityFlags();
32228
32229
32230
32231
32232
32233
32234
32235
32236 public function getReferences();
32237
32238
32239
32240
32241
32242
32243 public function getPreferStable();
32244
32245
32246
32247
32248
32249
32250 public function getConfig();
32251
32252
32253
32254
32255
32256
32257 public function setRequires(array $requires);
32258
32259
32260
32261
32262
32263
32264 public function setDevRequires(array $devRequires);
32265
32266
32267
32268
32269
32270
32271 public function setConflicts(array $conflicts);
32272
32273
32274
32275
32276
32277
32278 public function setProvides(array $provides);
32279
32280
32281
32282
32283
32284
32285 public function setReplaces(array $replaces);
32286
32287
32288
32289
32290
32291
32292 public function setRepositories($repositories);
32293
32294
32295
32296
32297
32298
32299 public function setAutoload(array $autoload);
32300
32301
32302
32303
32304
32305
32306 public function setDevAutoload(array $devAutoload);
32307
32308
32309
32310
32311
32312
32313 public function setStabilityFlags(array $stabilityFlags);
32314
32315
32316
32317
32318
32319
32320 public function setSuggests(array $suggests);
32321
32322
32323
32324
32325 public function setExtra(array $extra);
32326 }
32327 <?php
32328
32329
32330
32331
32332
32333
32334
32335
32336
32337
32338
32339 namespace Composer\Package\Version;
32340
32341 use Composer\Config;
32342 use Composer\Repository\Vcs\HgDriver;
32343 use Composer\IO\NullIO;
32344 use Composer\Semver\VersionParser as SemverVersionParser;
32345 use Composer\Util\Git as GitUtil;
32346 use Composer\Util\ProcessExecutor;
32347 use Composer\Util\Svn as SvnUtil;
32348
32349
32350
32351
32352
32353
32354
32355 class VersionGuesser
32356 {
32357
32358
32359
32360 private $config;
32361
32362
32363
32364
32365 private $process;
32366
32367
32368
32369
32370 private $versionParser;
32371
32372
32373
32374
32375
32376
32377 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
32378 {
32379 $this->config = $config;
32380 $this->process = $process;
32381 $this->versionParser = $versionParser;
32382 }
32383
32384
32385
32386
32387
32388
32389
32390 public function guessVersion(array $packageConfig, $path)
32391 {
32392 if (!function_exists('proc_open')) {
32393 return null;
32394 }
32395
32396 $versionData = $this->guessGitVersion($packageConfig, $path);
32397 if (null !== $versionData && null !== $versionData['version']) {
32398 return $this->postprocess($versionData);
32399 }
32400
32401 $versionData = $this->guessHgVersion($packageConfig, $path);
32402 if (null !== $versionData && null !== $versionData['version']) {
32403 return $this->postprocess($versionData);
32404 }
32405
32406 $versionData = $this->guessFossilVersion($packageConfig, $path);
32407 if (null !== $versionData && null !== $versionData['version']) {
32408 return $this->postprocess($versionData);
32409 }
32410
32411 $versionData = $this->guessSvnVersion($packageConfig, $path);
32412 if (null !== $versionData && null !== $versionData['version']) {
32413 return $this->postprocess($versionData);
32414 }
32415
32416 return null;
32417 }
32418
32419 private function postprocess(array $versionData)
32420 {
32421 if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version'] && $versionData['feature_pretty_version'] === $versionData['feature_pretty_version']) {
32422 unset($versionData['feature_version'], $versionData['feature_pretty_version']);
32423 }
32424
32425 if ('-dev' === substr($versionData['version'], -4) && preg_match('{\.9{7}}', $versionData['version'])) {
32426 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
32427 }
32428
32429 if (!empty($versionData['feature_version']) && '-dev' === substr($versionData['feature_version'], -4) && preg_match('{\.9{7}}', $versionData['feature_version'])) {
32430 $versionData['feature_pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['feature_version']);
32431 }
32432
32433 return $versionData;
32434 }
32435
32436 private function guessGitVersion(array $packageConfig, $path)
32437 {
32438 GitUtil::cleanEnv();
32439 $commit = null;
32440 $version = null;
32441 $prettyVersion = null;
32442 $featureVersion = null;
32443 $featurePrettyVersion = null;
32444 $isDetached = false;
32445
32446
32447 if (0 === $this->process->execute('git branch -a --no-color --no-abbrev -v', $output, $path)) {
32448 $branches = array();
32449 $isFeatureBranch = false;
32450
32451
32452 foreach ($this->process->splitLines($output) as $branch) {
32453 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
32454 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
32455 $version = 'dev-' . $match[2];
32456 $prettyVersion = $version;
32457 $isFeatureBranch = true;
32458 $isDetached = true;
32459 } else {
32460 $version = $this->versionParser->normalizeBranch($match[1]);
32461 $prettyVersion = 'dev-' . $match[1];
32462 $isFeatureBranch = 0 === strpos($version, 'dev-');
32463 }
32464
32465 if ($match[2]) {
32466 $commit = $match[2];
32467 }
32468 }
32469
32470 if ($branch && !preg_match('{^ *.+/HEAD }', $branch)) {
32471 if (preg_match('{^(?:\* )? *((?:remotes/(?:origin|upstream)/)?[^\s/]+) *([a-f0-9]+) .*$}', $branch, $match)) {
32472 $branches[] = $match[1];
32473 }
32474 }
32475 }
32476
32477 if ($isFeatureBranch) {
32478 $featureVersion = $version;
32479 $featurePrettyVersion = $prettyVersion;
32480
32481 $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
32482 $version = $result['version'];
32483 $prettyVersion = $result['pretty_version'];
32484 }
32485 }
32486
32487 if (!$version || $isDetached) {
32488 $result = $this->versionFromGitTags($path);
32489 if ($result) {
32490 $version = $result['version'];
32491 $prettyVersion = $result['pretty_version'];
32492 $featureVersion = null;
32493 $featurePrettyVersion = null;
32494 }
32495 }
32496
32497 if (!$commit) {
32498 $command = 'git log --pretty="%H" -n1 HEAD'.GitUtil::getNoShowSignatureFlag($this->process);
32499 if (0 === $this->process->execute($command, $output, $path)) {
32500 $commit = trim($output) ?: null;
32501 }
32502 }
32503
32504 if ($featureVersion) {
32505 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion, 'feature_version' => $featureVersion, 'feature_pretty_version' => $featurePrettyVersion);
32506 }
32507
32508 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
32509 }
32510
32511 private function versionFromGitTags($path)
32512 {
32513
32514 if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
32515 try {
32516 $version = $this->versionParser->normalize(trim($output));
32517
32518 return array('version' => $version, 'pretty_version' => trim($output));
32519 } catch (\Exception $e) {
32520 }
32521 }
32522
32523 return null;
32524 }
32525
32526 private function guessHgVersion(array $packageConfig, $path)
32527 {
32528
32529 if (0 === $this->process->execute('hg branch', $output, $path)) {
32530 $branch = trim($output);
32531 $version = $this->versionParser->normalizeBranch($branch);
32532 $isFeatureBranch = 0 === strpos($version, 'dev-');
32533
32534 if ('9999999-dev' === $version) {
32535 return array('version' => $version, 'commit' => null, 'pretty_version' => 'dev-'.$branch);
32536 }
32537
32538 if (!$isFeatureBranch) {
32539 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
32540 }
32541
32542
32543 $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
32544 $branches = array_keys($driver->getBranches());
32545
32546
32547 $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
32548 $result['commit'] = '';
32549 $result['feature_version'] = $version;
32550 $result['feature_pretty_version'] = $version;
32551
32552 return $result;
32553 }
32554 }
32555
32556 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
32557 {
32558 $prettyVersion = $version;
32559
32560
32561
32562 if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
32563 || strpos(json_encode($packageConfig), '"self.version"')
32564 ) {
32565 $branch = preg_replace('{^dev-}', '', $version);
32566 $length = PHP_INT_MAX;
32567
32568 $nonFeatureBranches = '';
32569 if (!empty($packageConfig['non-feature-branches'])) {
32570 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
32571 }
32572
32573
32574 if (preg_match('{^(' . $nonFeatureBranches . ')$}', $branch) && in_array($branch, $branches, true)) {
32575 return array('version' => $version, 'pretty_version' => $prettyVersion);
32576 }
32577
32578
32579
32580
32581 usort($branches, function ($a, $b) {
32582 $aRemote = 0 === strpos($a, 'remotes/');
32583 $bRemote = 0 === strpos($b, 'remotes/');
32584
32585 if ($aRemote !== $bRemote) {
32586 return $aRemote ? 1 : -1;
32587 }
32588
32589 return strnatcasecmp($b, $a);
32590 });
32591
32592 foreach ($branches as $candidate) {
32593 $candidateVersion = preg_replace('{^remotes/\S+/}', '', $candidate);
32594
32595
32596 if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidateVersion, $match)) {
32597 continue;
32598 }
32599
32600 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
32601 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
32602 continue;
32603 }
32604
32605 if (strlen($output) < $length) {
32606 $length = strlen($output);
32607 $version = $this->versionParser->normalizeBranch($candidateVersion);
32608 $prettyVersion = 'dev-' . $candidateVersion;
32609 if ($length === 0) {
32610 break;
32611 }
32612 }
32613 }
32614 }
32615
32616 return array('version' => $version, 'pretty_version' => $prettyVersion);
32617 }
32618
32619 private function guessFossilVersion(array $packageConfig, $path)
32620 {
32621 $version = null;
32622 $prettyVersion = null;
32623
32624
32625 if (0 === $this->process->execute('fossil branch list', $output, $path)) {
32626 $branch = trim($output);
32627 $version = $this->versionParser->normalizeBranch($branch);
32628 $prettyVersion = 'dev-' . $branch;
32629 }
32630
32631
32632 if (0 === $this->process->execute('fossil tag list', $output, $path)) {
32633 try {
32634 $version = $this->versionParser->normalize(trim($output));
32635 $prettyVersion = trim($output);
32636 } catch (\Exception $e) {
32637 }
32638 }
32639
32640 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
32641 }
32642
32643 private function guessSvnVersion(array $packageConfig, $path)
32644 {
32645 SvnUtil::cleanEnv();
32646
32647
32648 if (0 === $this->process->execute('svn info --xml', $output, $path)) {
32649 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
32650 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
32651 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
32652
32653 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
32654
32655 if (preg_match($urlPattern, $output, $matches)) {
32656 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
32657
32658 $version = $this->versionParser->normalizeBranch($matches[3]);
32659 $prettyVersion = 'dev-' . $matches[3];
32660
32661 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
32662 }
32663
32664 $prettyVersion = trim($matches[1]);
32665 $version = $this->versionParser->normalize($prettyVersion);
32666
32667 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
32668 }
32669 }
32670 }
32671 }
32672 <?php
32673
32674
32675
32676
32677
32678
32679
32680
32681
32682
32683
32684 namespace Composer\Package\Version;
32685
32686 use Composer\Repository\PlatformRepository;
32687 use Composer\Semver\VersionParser as SemverVersionParser;
32688 use Composer\Semver\Semver;
32689
32690 class VersionParser extends SemverVersionParser
32691 {
32692 private static $constraints = array();
32693
32694
32695
32696
32697 public function parseConstraints($constraints)
32698 {
32699 if (!isset(self::$constraints[$constraints])) {
32700 self::$constraints[$constraints] = parent::parseConstraints($constraints);
32701 }
32702
32703 return self::$constraints[$constraints];
32704 }
32705
32706
32707
32708
32709
32710
32711
32712
32713
32714
32715
32716 public function parseNameVersionPairs(array $pairs)
32717 {
32718 $pairs = array_values($pairs);
32719 $result = array();
32720
32721 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
32722 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
32723 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
32724 $pair .= ' '.$pairs[$i + 1];
32725 $i++;
32726 }
32727
32728 if (strpos($pair, ' ')) {
32729 list($name, $version) = explode(' ', $pair, 2);
32730 $result[] = array('name' => $name, 'version' => $version);
32731 } else {
32732 $result[] = array('name' => $pair);
32733 }
32734 }
32735
32736 return $result;
32737 }
32738
32739
32740
32741
32742 public static function isUpgrade($normalizedFrom, $normalizedTo)
32743 {
32744 if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') {
32745 return true;
32746 }
32747
32748 $sorted = Semver::sort(array($normalizedTo, $normalizedFrom));
32749
32750 return $sorted[0] === $normalizedFrom;
32751 }
32752 }
32753 <?php
32754
32755
32756
32757
32758
32759
32760
32761
32762
32763
32764
32765 namespace Composer\Package\Version;
32766
32767 use Composer\DependencyResolver\Pool;
32768 use Composer\Package\BasePackage;
32769 use Composer\Package\PackageInterface;
32770 use Composer\Plugin\PluginInterface;
32771 use Composer\Composer;
32772 use Composer\Package\Loader\ArrayLoader;
32773 use Composer\Package\Dumper\ArrayDumper;
32774 use Composer\Semver\Constraint\Constraint;
32775
32776
32777
32778
32779
32780
32781
32782 class VersionSelector
32783 {
32784 private $pool;
32785
32786 private $parser;
32787
32788 public function __construct(Pool $pool)
32789 {
32790 $this->pool = $pool;
32791 }
32792
32793
32794
32795
32796
32797
32798
32799
32800
32801
32802
32803 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
32804 {
32805 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
32806 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
32807
32808 if ($targetPhpVersion) {
32809 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
32810 $composerRuntimeConstraint = new Constraint('==', $this->getParser()->normalize(Composer::RUNTIME_API_VERSION));
32811 $composerPluginConstraint = new Constraint('==', $this->getParser()->normalize(PluginInterface::PLUGIN_API_VERSION));
32812 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint, $composerPluginConstraint, $composerRuntimeConstraint) {
32813 $reqs = $pkg->getRequires();
32814
32815 return (!isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint))
32816 && (!isset($reqs['composer-plugin-api']) || $reqs['composer-plugin-api']->getConstraint()->matches($composerPluginConstraint))
32817 && (!isset($reqs['composer-runtime-api']) || $reqs['composer-runtime-api']->getConstraint()->matches($composerRuntimeConstraint));
32818 });
32819 }
32820
32821 if (!$candidates) {
32822 return false;
32823 }
32824
32825
32826 $package = reset($candidates);
32827 $minPriority = BasePackage::$stabilities[$preferredStability];
32828 foreach ($candidates as $candidate) {
32829 $candidatePriority = $candidate->getStabilityPriority();
32830 $currentPriority = $package->getStabilityPriority();
32831
32832
32833
32834 if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
32835 continue;
32836 }
32837
32838
32839
32840 if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
32841 $package = $candidate;
32842 continue;
32843 }
32844
32845
32846
32847 if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
32848 $package = $candidate;
32849 continue;
32850 }
32851
32852
32853 if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
32854 $package = $candidate;
32855 }
32856 }
32857
32858 return $package;
32859 }
32860
32861
32862
32863
32864
32865
32866
32867
32868
32869
32870
32871
32872
32873
32874
32875
32876 public function findRecommendedRequireVersion(PackageInterface $package)
32877 {
32878 $version = $package->getVersion();
32879 if (!$package->isDev()) {
32880 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
32881 }
32882
32883 $loader = new ArrayLoader($this->getParser());
32884 $dumper = new ArrayDumper();
32885 $extra = $loader->getBranchAlias($dumper->dump($package));
32886 if ($extra) {
32887 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
32888 if ($count) {
32889 $extra = str_replace('.9999999', '.0', $extra);
32890
32891 return $this->transformVersion($extra, $extra, 'dev');
32892 }
32893 }
32894
32895 return $package->getPrettyVersion();
32896 }
32897
32898 private function transformVersion($version, $prettyVersion, $stability)
32899 {
32900
32901
32902 $semanticVersionParts = explode('.', $version);
32903
32904
32905 if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
32906
32907 if ($semanticVersionParts[0] === '0') {
32908 unset($semanticVersionParts[3]);
32909 } else {
32910 unset($semanticVersionParts[2], $semanticVersionParts[3]);
32911 }
32912 $version = implode('.', $semanticVersionParts);
32913 } else {
32914 return $prettyVersion;
32915 }
32916
32917
32918 if ($stability != 'stable') {
32919 $version .= '@'.$stability;
32920 }
32921
32922
32923 return '^' . $version;
32924 }
32925
32926 private function getParser()
32927 {
32928 if ($this->parser === null) {
32929 $this->parser = new VersionParser();
32930 }
32931
32932 return $this->parser;
32933 }
32934 }
32935 <?php
32936
32937
32938
32939
32940
32941
32942
32943
32944
32945
32946
32947 namespace Composer\Plugin\Capability;
32948
32949
32950
32951
32952
32953
32954
32955 interface Capability
32956 {
32957 }
32958 <?php
32959
32960
32961
32962
32963
32964
32965
32966
32967
32968
32969
32970 namespace Composer\Plugin\Capability;
32971
32972
32973
32974
32975
32976
32977
32978
32979
32980
32981
32982 interface CommandProvider extends Capability
32983 {
32984
32985
32986
32987
32988
32989 public function getCommands();
32990 }
32991 <?php
32992
32993
32994
32995
32996
32997
32998
32999
33000
33001
33002
33003 namespace Composer\Plugin;
33004
33005
33006
33007
33008
33009
33010
33011
33012 interface Capable
33013 {
33014
33015
33016
33017
33018
33019
33020
33021
33022
33023
33024
33025
33026
33027
33028
33029
33030
33031
33032 public function getCapabilities();
33033 }
33034 <?php
33035
33036
33037
33038
33039
33040
33041
33042
33043
33044
33045
33046 namespace Composer\Plugin;
33047
33048 use Composer\EventDispatcher\Event;
33049 use Symfony\Component\Console\Input\InputInterface;
33050 use Symfony\Component\Console\Output\OutputInterface;
33051
33052
33053
33054
33055
33056
33057 class CommandEvent extends Event
33058 {
33059
33060
33061
33062 private $commandName;
33063
33064
33065
33066
33067 private $input;
33068
33069
33070
33071
33072 private $output;
33073
33074
33075
33076
33077
33078
33079
33080
33081
33082
33083
33084 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
33085 {
33086 parent::__construct($name, $args, $flags);
33087 $this->commandName = $commandName;
33088 $this->input = $input;
33089 $this->output = $output;
33090 }
33091
33092
33093
33094
33095
33096
33097 public function getInput()
33098 {
33099 return $this->input;
33100 }
33101
33102
33103
33104
33105
33106
33107 public function getOutput()
33108 {
33109 return $this->output;
33110 }
33111
33112
33113
33114
33115
33116
33117 public function getCommandName()
33118 {
33119 return $this->commandName;
33120 }
33121 }
33122 <?php
33123
33124
33125
33126
33127
33128
33129
33130
33131
33132
33133
33134 namespace Composer\Plugin;
33135
33136
33137
33138
33139
33140
33141 class PluginEvents
33142 {
33143
33144
33145
33146
33147
33148
33149
33150
33151 const INIT = 'init';
33152
33153
33154
33155
33156
33157
33158
33159
33160
33161 const COMMAND = 'command';
33162
33163
33164
33165
33166
33167
33168
33169
33170
33171 const PRE_FILE_DOWNLOAD = 'pre-file-download';
33172
33173
33174
33175
33176
33177
33178
33179
33180
33181 const PRE_COMMAND_RUN = 'pre-command-run';
33182 }
33183 <?php
33184
33185
33186
33187
33188
33189
33190
33191
33192
33193
33194
33195 namespace Composer\Plugin;
33196
33197 use Composer\Composer;
33198 use Composer\IO\IOInterface;
33199
33200
33201
33202
33203
33204
33205 interface PluginInterface
33206 {
33207
33208
33209
33210
33211
33212 const PLUGIN_API_VERSION = '1.1.0';
33213
33214
33215
33216
33217
33218
33219
33220 public function activate(Composer $composer, IOInterface $io);
33221 }
33222 <?php
33223
33224
33225
33226
33227
33228
33229
33230
33231
33232
33233
33234 namespace Composer\Plugin;
33235
33236 use Composer\Composer;
33237 use Composer\EventDispatcher\EventSubscriberInterface;
33238 use Composer\IO\IOInterface;
33239 use Composer\Package\CompletePackage;
33240 use Composer\Package\Package;
33241 use Composer\Package\Version\VersionParser;
33242 use Composer\Repository\RepositoryInterface;
33243 use Composer\Package\PackageInterface;
33244 use Composer\Package\Link;
33245 use Composer\Semver\Constraint\Constraint;
33246 use Composer\DependencyResolver\Pool;
33247 use Composer\Plugin\Capability\Capability;
33248 use Composer\Util\PackageSorter;
33249
33250
33251
33252
33253
33254
33255
33256 class PluginManager
33257 {
33258 protected $composer;
33259 protected $io;
33260 protected $globalComposer;
33261 protected $versionParser;
33262 protected $disablePlugins = false;
33263
33264 protected $plugins = array();
33265 protected $registeredPlugins = array();
33266
33267 private static $classCounter = 0;
33268
33269
33270
33271
33272
33273
33274
33275
33276
33277 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
33278 {
33279 $this->io = $io;
33280 $this->composer = $composer;
33281 $this->globalComposer = $globalComposer;
33282 $this->versionParser = new VersionParser();
33283 $this->disablePlugins = $disablePlugins;
33284 }
33285
33286
33287
33288
33289 public function loadInstalledPlugins()
33290 {
33291 if ($this->disablePlugins) {
33292 return;
33293 }
33294
33295 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
33296 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
33297 if ($repo) {
33298 $this->loadRepository($repo);
33299 }
33300 if ($globalRepo) {
33301 $this->loadRepository($globalRepo);
33302 }
33303 }
33304
33305
33306
33307
33308
33309
33310 public function getPlugins()
33311 {
33312 return $this->plugins;
33313 }
33314
33315
33316
33317
33318
33319
33320 public function getGlobalComposer()
33321 {
33322 return $this->globalComposer;
33323 }
33324
33325
33326
33327
33328
33329
33330
33331
33332
33333
33334
33335
33336 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
33337 {
33338 if ($this->disablePlugins) {
33339 return;
33340 }
33341
33342 if ($package->getType() === 'composer-plugin') {
33343 $requiresComposer = null;
33344 foreach ($package->getRequires() as $link) { 
33345 if ('composer-plugin-api' === $link->getTarget()) {
33346 $requiresComposer = $link->getConstraint();
33347 break;
33348 }
33349 }
33350
33351 if (!$requiresComposer) {
33352 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
33353 }
33354
33355 $currentPluginApiVersion = $this->getPluginApiVersion();
33356 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
33357
33358 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
33359 $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>');
33360 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
33361 $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>');
33362
33363 return;
33364 }
33365 }
33366
33367 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
33368
33369 if (in_array($package->getName(), $this->registeredPlugins)) {
33370 return;
33371 }
33372
33373 $extra = $package->getExtra();
33374 if (empty($extra['class'])) {
33375 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
33376 }
33377 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
33378
33379 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
33380 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
33381
33382 $pool = new Pool('dev');
33383 $pool->addRepository($localRepo);
33384 if ($globalRepo) {
33385 $pool->addRepository($globalRepo);
33386 }
33387
33388 $autoloadPackages = array($package->getName() => $package);
33389 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
33390
33391 $generator = $this->composer->getAutoloadGenerator();
33392 $autoloads = array();
33393 foreach ($autoloadPackages as $autoloadPackage) {
33394 $downloadPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage));
33395 $autoloads[] = array($autoloadPackage, $downloadPath);
33396 }
33397
33398 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
33399 $classLoader = $generator->createLoader($map);
33400 $classLoader->register();
33401
33402 foreach ($classes as $class) {
33403 if (class_exists($class, false)) {
33404 $class = trim($class, '\\');
33405 $path = $classLoader->findFile($class);
33406 $code = file_get_contents($path);
33407 $separatorPos = strrpos($class, '\\');
33408 $className = $class;
33409 if ($separatorPos) {
33410 $className = substr($class, $separatorPos + 1);
33411 }
33412 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
33413 $code = str_replace('__FILE__', var_export($path, true), $code);
33414 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
33415 $code = str_replace('__CLASS__', var_export($class, true), $code);
33416 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
33417 eval($code);
33418 $class .= '_composer_tmp'.self::$classCounter;
33419 self::$classCounter++;
33420 }
33421
33422 if ($oldInstallerPlugin) {
33423 $installer = new $class($this->io, $this->composer);
33424 $this->composer->getInstallationManager()->addInstaller($installer);
33425 } elseif (class_exists($class)) {
33426 $plugin = new $class();
33427 $this->addPlugin($plugin);
33428 $this->registeredPlugins[] = $package->getName();
33429 } elseif ($failOnMissingClasses) {
33430 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
33431 }
33432 }
33433 }
33434
33435
33436
33437
33438
33439
33440 protected function getPluginApiVersion()
33441 {
33442 return PluginInterface::PLUGIN_API_VERSION;
33443 }
33444
33445
33446
33447
33448
33449
33450
33451
33452
33453
33454 public function addPlugin(PluginInterface $plugin)
33455 {
33456 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
33457 $this->plugins[] = $plugin;
33458 $plugin->activate($this->composer, $this->io);
33459
33460 if ($plugin instanceof EventSubscriberInterface) {
33461 $this->composer->getEventDispatcher()->addSubscriber($plugin);
33462 }
33463 }
33464
33465
33466
33467
33468
33469
33470
33471
33472
33473
33474
33475
33476 private function loadRepository(RepositoryInterface $repo)
33477 {
33478 $packages = $repo->getPackages();
33479 $sortedPackages = array_reverse(PackageSorter::sortPackages($packages));
33480 foreach ($sortedPackages as $package) {
33481 if (!($package instanceof CompletePackage)) {
33482 continue;
33483 }
33484 if ('composer-plugin' === $package->getType()) {
33485 $this->registerPackage($package);
33486
33487 } elseif ('composer-installer' === $package->getType()) {
33488 $this->registerPackage($package);
33489 }
33490 }
33491 }
33492
33493
33494
33495
33496
33497
33498
33499
33500
33501
33502 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
33503 {
33504 $requires = array_merge(
33505 $package->getRequires(),
33506 $package->getDevRequires()
33507 );
33508
33509 foreach ($requires as $requireLink) {
33510 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
33511 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
33512 $collected[$requiredPackage->getName()] = $requiredPackage;
33513 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
33514 }
33515 }
33516
33517 return $collected;
33518 }
33519
33520
33521
33522
33523
33524
33525
33526
33527
33528
33529
33530 private function lookupInstalledPackage(Pool $pool, Link $link)
33531 {
33532 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
33533
33534 return !empty($packages) ? $packages[0] : null;
33535 }
33536
33537
33538
33539
33540
33541
33542
33543
33544
33545 private function getInstallPath(PackageInterface $package, $global = false)
33546 {
33547 if (!$global) {
33548 return $this->composer->getInstallationManager()->getInstallPath($package);
33549 }
33550
33551 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
33552 }
33553
33554
33555
33556
33557
33558
33559
33560 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
33561 {
33562 if (!($plugin instanceof Capable)) {
33563 return null;
33564 }
33565
33566 $capabilities = (array) $plugin->getCapabilities();
33567
33568 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
33569 return trim($capabilities[$capability]);
33570 }
33571
33572 if (
33573 array_key_exists($capability, $capabilities)
33574 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
33575 ) {
33576 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
33577 }
33578 }
33579
33580
33581
33582
33583
33584
33585
33586
33587
33588 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
33589 {
33590 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
33591 if (!class_exists($capabilityClass)) {
33592 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
33593 }
33594
33595 $ctorArgs['plugin'] = $plugin;
33596 $capabilityObj = new $capabilityClass($ctorArgs);
33597
33598
33599 if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
33600 throw new \RuntimeException(
33601 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
33602 );
33603 }
33604
33605 return $capabilityObj;
33606 }
33607 }
33608
33609
33610
33611
33612
33613
33614
33615
33616 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
33617 {
33618 $capabilities = array();
33619 foreach ($this->getPlugins() as $plugin) {
33620 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
33621 $capabilities[] = $capability;
33622 }
33623 }
33624
33625 return $capabilities;
33626 }
33627 }
33628 <?php
33629
33630
33631
33632
33633
33634
33635
33636
33637
33638
33639
33640 namespace Composer\Plugin;
33641
33642 use Composer\EventDispatcher\Event;
33643 use Symfony\Component\Console\Input\InputInterface;
33644
33645
33646
33647
33648
33649
33650 class PreCommandRunEvent extends Event
33651 {
33652
33653
33654
33655 private $input;
33656
33657
33658
33659
33660 private $command;
33661
33662
33663
33664
33665
33666
33667
33668
33669 public function __construct($name, InputInterface $input, $command)
33670 {
33671 parent::__construct($name);
33672 $this->input = $input;
33673 $this->command = $command;
33674 }
33675
33676
33677
33678
33679
33680
33681 public function getInput()
33682 {
33683 return $this->input;
33684 }
33685
33686
33687
33688
33689
33690
33691 public function getCommand()
33692 {
33693 return $this->command;
33694 }
33695 }
33696 <?php
33697
33698
33699
33700
33701
33702
33703
33704
33705
33706
33707
33708 namespace Composer\Plugin;
33709
33710 use Composer\EventDispatcher\Event;
33711 use Composer\Util\RemoteFilesystem;
33712
33713
33714
33715
33716
33717
33718 class PreFileDownloadEvent extends Event
33719 {
33720
33721
33722
33723 private $rfs;
33724
33725
33726
33727
33728 private $processedUrl;
33729
33730
33731
33732
33733
33734
33735
33736
33737 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
33738 {
33739 parent::__construct($name);
33740 $this->rfs = $rfs;
33741 $this->processedUrl = $processedUrl;
33742 }
33743
33744
33745
33746
33747
33748
33749 public function getRemoteFilesystem()
33750 {
33751 return $this->rfs;
33752 }
33753
33754
33755
33756
33757
33758
33759 public function setRemoteFilesystem(RemoteFilesystem $rfs)
33760 {
33761 $this->rfs = $rfs;
33762 }
33763
33764
33765
33766
33767
33768
33769 public function getProcessedUrl()
33770 {
33771 return $this->processedUrl;
33772 }
33773 }
33774 <?php
33775
33776
33777
33778
33779
33780
33781
33782
33783
33784
33785
33786 namespace Composer\Question;
33787
33788 use Symfony\Component\Console\Exception\InvalidArgumentException;
33789 use Symfony\Component\Console\Question\Question;
33790
33791
33792
33793
33794
33795
33796
33797
33798 class StrictConfirmationQuestion extends Question
33799 {
33800 private $trueAnswerRegex;
33801 private $falseAnswerRegex;
33802
33803
33804
33805
33806
33807
33808
33809
33810
33811 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
33812 {
33813 parent::__construct($question, (bool) $default);
33814
33815 $this->trueAnswerRegex = $trueAnswerRegex;
33816 $this->falseAnswerRegex = $falseAnswerRegex;
33817 $this->setNormalizer($this->getDefaultNormalizer());
33818 $this->setValidator($this->getDefaultValidator());
33819 }
33820
33821
33822
33823
33824
33825
33826 private function getDefaultNormalizer()
33827 {
33828 $default = $this->getDefault();
33829 $trueRegex = $this->trueAnswerRegex;
33830 $falseRegex = $this->falseAnswerRegex;
33831
33832 return function ($answer) use ($default, $trueRegex, $falseRegex) {
33833 if (is_bool($answer)) {
33834 return $answer;
33835 }
33836 if (empty($answer) && !empty($default)) {
33837 return $default;
33838 }
33839
33840 if (preg_match($trueRegex, $answer)) {
33841 return true;
33842 }
33843
33844 if (preg_match($falseRegex, $answer)) {
33845 return false;
33846 }
33847
33848 return null;
33849 };
33850 }
33851
33852
33853
33854
33855
33856
33857 private function getDefaultValidator()
33858 {
33859 return function ($answer) {
33860 if (!is_bool($answer)) {
33861 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
33862 }
33863
33864 return $answer;
33865 };
33866 }
33867 }
33868 <?php
33869
33870
33871
33872
33873
33874
33875
33876
33877
33878
33879
33880 namespace Composer\Repository;
33881
33882 use Composer\Package\AliasPackage;
33883 use Composer\Package\PackageInterface;
33884 use Composer\Package\CompletePackageInterface;
33885 use Composer\Package\Version\VersionParser;
33886 use Composer\Semver\Constraint\ConstraintInterface;
33887 use Composer\Semver\Constraint\Constraint;
33888
33889
33890
33891
33892
33893
33894 class ArrayRepository extends BaseRepository
33895 {
33896
33897 protected $packages;
33898
33899
33900
33901
33902 protected $packageMap;
33903
33904 public function __construct(array $packages = array())
33905 {
33906 foreach ($packages as $package) {
33907 $this->addPackage($package);
33908 }
33909 }
33910
33911
33912
33913
33914 public function findPackage($name, $constraint)
33915 {
33916 $name = strtolower($name);
33917
33918 if (!$constraint instanceof ConstraintInterface) {
33919 $versionParser = new VersionParser();
33920 $constraint = $versionParser->parseConstraints($constraint);
33921 }
33922
33923 foreach ($this->getPackages() as $package) {
33924 if ($name === $package->getName()) {
33925 $pkgConstraint = new Constraint('==', $package->getVersion());
33926 if ($constraint->matches($pkgConstraint)) {
33927 return $package;
33928 }
33929 }
33930 }
33931
33932 return null;
33933 }
33934
33935
33936
33937
33938 public function findPackages($name, $constraint = null)
33939 {
33940
33941 $name = strtolower($name);
33942 $packages = array();
33943
33944 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
33945 $versionParser = new VersionParser();
33946 $constraint = $versionParser->parseConstraints($constraint);
33947 }
33948
33949 foreach ($this->getPackages() as $package) {
33950 if ($name === $package->getName()) {
33951 $pkgConstraint = new Constraint('==', $package->getVersion());
33952 if (null === $constraint || $constraint->matches($pkgConstraint)) {
33953 $packages[] = $package;
33954 }
33955 }
33956 }
33957
33958 return $packages;
33959 }
33960
33961
33962
33963
33964 public function search($query, $mode = 0, $type = null)
33965 {
33966 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
33967
33968 $matches = array();
33969 foreach ($this->getPackages() as $package) {
33970 $name = $package->getName();
33971 if (isset($matches[$name])) {
33972 continue;
33973 }
33974 if (preg_match($regex, $name)
33975 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
33976 ) {
33977 if (null !== $type && $package->getType() !== $type) {
33978 continue;
33979 }
33980
33981 $matches[$name] = array(
33982 'name' => $package->getPrettyName(),
33983 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
33984 );
33985 }
33986 }
33987
33988 return array_values($matches);
33989 }
33990
33991
33992
33993
33994 public function hasPackage(PackageInterface $package)
33995 {
33996 if ($this->packageMap === null) {
33997 $this->packageMap = array();
33998 foreach ($this->getPackages() as $repoPackage) {
33999 $this->packageMap[$repoPackage->getUniqueName()] = $repoPackage;
34000 }
34001 }
34002
34003 return isset($this->packageMap[$package->getUniqueName()]);
34004 }
34005
34006
34007
34008
34009
34010
34011 public function addPackage(PackageInterface $package)
34012 {
34013 if (null === $this->packages) {
34014 $this->initialize();
34015 }
34016 $package->setRepository($this);
34017 $this->packages[] = $package;
34018
34019 if ($package instanceof AliasPackage) {
34020 $aliasedPackage = $package->getAliasOf();
34021 if (null === $aliasedPackage->getRepository()) {
34022 $this->addPackage($aliasedPackage);
34023 }
34024 }
34025
34026
34027 $this->packageMap = null;
34028 }
34029
34030 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
34031 {
34032 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
34033 }
34034
34035
34036
34037
34038
34039
34040 public function removePackage(PackageInterface $package)
34041 {
34042 $packageId = $package->getUniqueName();
34043
34044 foreach ($this->getPackages() as $key => $repoPackage) {
34045 if ($packageId === $repoPackage->getUniqueName()) {
34046 array_splice($this->packages, $key, 1);
34047
34048
34049 $this->packageMap = null;
34050
34051 return;
34052 }
34053 }
34054 }
34055
34056
34057
34058
34059 public function getPackages()
34060 {
34061 if (null === $this->packages) {
34062 $this->initialize();
34063 }
34064
34065 return $this->packages;
34066 }
34067
34068
34069
34070
34071
34072
34073 public function count()
34074 {
34075 return count($this->packages);
34076 }
34077
34078
34079
34080
34081 protected function initialize()
34082 {
34083 $this->packages = array();
34084 }
34085 }
34086 <?php
34087
34088
34089
34090
34091
34092
34093
34094
34095
34096
34097
34098 namespace Composer\Repository;
34099
34100 use Composer\IO\IOInterface;
34101 use Composer\Json\JsonFile;
34102 use Composer\Package\Loader\ArrayLoader;
34103 use Composer\Package\Loader\LoaderInterface;
34104 use Composer\Util\Zip;
34105
34106
34107
34108
34109 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
34110 {
34111
34112 protected $loader;
34113
34114 protected $lookup;
34115 protected $repoConfig;
34116 private $io;
34117
34118 public function __construct(array $repoConfig, IOInterface $io)
34119 {
34120 parent::__construct();
34121 if (!extension_loaded('zip')) {
34122 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
34123 }
34124
34125 $this->loader = new ArrayLoader();
34126 $this->lookup = $repoConfig['url'];
34127 $this->io = $io;
34128 $this->repoConfig = $repoConfig;
34129 }
34130
34131 public function getRepoConfig()
34132 {
34133 return $this->repoConfig;
34134 }
34135
34136 protected function initialize()
34137 {
34138 parent::initialize();
34139
34140 $this->scanDirectory($this->lookup);
34141 }
34142
34143 private function scanDirectory($path)
34144 {
34145 $io = $this->io;
34146
34147 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
34148 $iterator = new \RecursiveIteratorIterator($directory);
34149 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
34150 foreach ($regex as $file) {
34151
34152 if (!$file->isFile()) {
34153 continue;
34154 }
34155
34156 $package = $this->getComposerInformation($file);
34157 if (!$package) {
34158 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
34159 continue;
34160 }
34161
34162 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
34163 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
34164
34165 $this->addPackage($package);
34166 }
34167 }
34168
34169 private function getComposerInformation(\SplFileInfo $file)
34170 {
34171 $json = Zip::getComposerJson($file->getPathname());
34172
34173 if (null === $json) {
34174 return false;
34175 }
34176
34177 $package = JsonFile::parseJson($json, $file->getPathname().'#composer.json');
34178 $package['dist'] = array(
34179 'type' => 'zip',
34180 'url' => strtr($file->getPathname(), '\\', '/'),
34181 'shasum' => sha1_file($file->getRealPath()),
34182 );
34183
34184 try {
34185 $package = $this->loader->load($package);
34186 } catch (\UnexpectedValueException $e) {
34187 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
34188 }
34189
34190 return $package;
34191 }
34192 }
34193 <?php
34194
34195
34196
34197
34198
34199
34200
34201
34202
34203
34204
34205 namespace Composer\Repository;
34206
34207 use Composer\Package\RootPackageInterface;
34208 use Composer\Semver\Constraint\ConstraintInterface;
34209 use Composer\Semver\Constraint\Constraint;
34210 use Composer\Package\Link;
34211
34212
34213
34214
34215
34216
34217 abstract class BaseRepository implements RepositoryInterface
34218 {
34219
34220
34221
34222
34223
34224
34225
34226
34227
34228
34229
34230
34231
34232 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
34233 {
34234 $needles = array_map('strtolower', (array) $needle);
34235 $results = array();
34236
34237
34238 if (null === $packagesFound) {
34239 $packagesFound = $needles;
34240 }
34241
34242
34243 $rootPackage = null;
34244 foreach ($this->getPackages() as $package) {
34245 if ($package instanceof RootPackageInterface) {
34246 $rootPackage = $package;
34247 break;
34248 }
34249 }
34250
34251
34252 foreach ($this->getPackages() as $package) {
34253 $links = $package->getRequires();
34254
34255
34256
34257 $packagesInTree = $packagesFound;
34258
34259
34260 if (!$invert) {
34261 $links += $package->getReplaces();
34262
34263
34264
34265
34266 foreach ($package->getReplaces() as $link) {
34267 foreach ($needles as $needle) {
34268 if ($link->getSource() === $needle) {
34269 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
34270
34271 if (in_array($link->getTarget(), $packagesInTree)) {
34272 $results[] = array($package, $link, false);
34273 continue;
34274 }
34275 $packagesInTree[] = $link->getTarget();
34276 $dependents = $recurse ? $this->getDependents($link->getTarget(), null, false, true, $packagesInTree) : array();
34277 $results[] = array($package, $link, $dependents);
34278 $needles[] = $link->getTarget();
34279 }
34280 }
34281 }
34282 }
34283 }
34284
34285
34286 if ($package instanceof RootPackageInterface) {
34287 $links += $package->getDevRequires();
34288 }
34289
34290
34291 foreach ($links as $link) {
34292 foreach ($needles as $needle) {
34293 if ($link->getTarget() === $needle) {
34294 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
34295
34296 if (in_array($link->getSource(), $packagesInTree)) {
34297 $results[] = array($package, $link, false);
34298 continue;
34299 }
34300 $packagesInTree[] = $link->getSource();
34301 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
34302 $results[] = array($package, $link, $dependents);
34303 }
34304 }
34305 }
34306 }
34307
34308
34309 if ($invert && in_array($package->getName(), $needles)) {
34310 foreach ($package->getConflicts() as $link) {
34311 foreach ($this->findPackages($link->getTarget()) as $pkg) {
34312 $version = new Constraint('=', $pkg->getVersion());
34313 if ($link->getConstraint()->matches($version) === $invert) {
34314 $results[] = array($package, $link, false);
34315 }
34316 }
34317 }
34318 }
34319
34320
34321 if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
34322 foreach ($package->getRequires() as $link) {
34323 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
34324 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
34325 continue;
34326 }
34327
34328 $platformPkg = $this->findPackage($link->getTarget(), '*');
34329 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
34330 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
34331
34332 continue;
34333 }
34334
34335 foreach ($this->getPackages() as $pkg) {
34336 if (!in_array($link->getTarget(), $pkg->getNames())) {
34337 continue;
34338 }
34339
34340 $version = new Constraint('=', $pkg->getVersion());
34341
34342 if ($link->getTarget() !== $pkg->getName()) {
34343 foreach (array_merge($pkg->getReplaces(), $pkg->getProvides()) as $prov) {
34344 if ($link->getTarget() === $prov->getTarget()) {
34345 $version = $prov->getConstraint();
34346 break;
34347 }
34348 }
34349 }
34350
34351 if (!$link->getConstraint()->matches($version)) {
34352
34353
34354 if ($rootPackage) {
34355 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
34356 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
34357 $results[] = array($package, $link, false);
34358 $results[] = array($rootPackage, $rootReq, false);
34359 continue 3;
34360 }
34361 }
34362
34363 $results[] = array($package, $link, false);
34364 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
34365 } else {
34366
34367 $results[] = array($package, $link, false);
34368 }
34369 }
34370
34371 continue 2;
34372 }
34373 }
34374 }
34375 }
34376
34377 ksort($results);
34378
34379 return $results;
34380 }
34381 }
34382 <?php
34383
34384
34385
34386
34387
34388
34389
34390
34391
34392
34393
34394 namespace Composer\Repository;
34395
34396 use Composer\Package\Loader\ArrayLoader;
34397 use Composer\Package\PackageInterface;
34398 use Composer\Package\AliasPackage;
34399 use Composer\Package\Version\VersionParser;
34400 use Composer\DependencyResolver\Pool;
34401 use Composer\Json\JsonFile;
34402 use Composer\Cache;
34403 use Composer\Config;
34404 use Composer\Composer;
34405 use Composer\Factory;
34406 use Composer\IO\IOInterface;
34407 use Composer\Util\RemoteFilesystem;
34408 use Composer\Plugin\PluginEvents;
34409 use Composer\Plugin\PreFileDownloadEvent;
34410 use Composer\EventDispatcher\EventDispatcher;
34411 use Composer\Downloader\TransportException;
34412 use Composer\Semver\Constraint\ConstraintInterface;
34413 use Composer\Semver\Constraint\Constraint;
34414
34415
34416
34417
34418 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
34419 {
34420 protected $config;
34421 protected $repoConfig;
34422 protected $options;
34423 protected $url;
34424 protected $baseUrl;
34425 protected $io;
34426 protected $rfs;
34427 protected $cache;
34428 protected $notifyUrl;
34429 protected $searchUrl;
34430 protected $hasProviders = false;
34431 protected $providersUrl;
34432 protected $lazyProvidersUrl;
34433 protected $providerListing;
34434 protected $providers = array();
34435 protected $providersByUid = array();
34436 protected $loader;
34437 protected $rootAliases;
34438 protected $allowSslDowngrade = false;
34439 protected $eventDispatcher;
34440 protected $sourceMirrors;
34441 protected $distMirrors;
34442 private $degradedMode = false;
34443 private $rootData;
34444 private $hasPartialPackages;
34445 private $partialPackagesByName;
34446
34447 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34448 {
34449 parent::__construct();
34450 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
34451
34452 $repoConfig['url'] = 'http://'.$repoConfig['url'];
34453 }
34454 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
34455
34456 if ('https?' === substr($repoConfig['url'], 0, 6)) {
34457 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
34458 }
34459
34460 $urlBits = parse_url($repoConfig['url']);
34461 if ($urlBits === false || empty($urlBits['scheme'])) {
34462 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
34463 }
34464
34465 if (!isset($repoConfig['options'])) {
34466 $repoConfig['options'] = array();
34467 }
34468 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
34469 $this->allowSslDowngrade = true;
34470 }
34471
34472 $this->config = $config;
34473 $this->options = $repoConfig['options'];
34474 $this->url = $repoConfig['url'];
34475
34476
34477 if (preg_match('{^(?P<proto>https?)://packagist\.org/?$}i', $this->url, $match)) {
34478 $this->url = $match['proto'].'://repo.packagist.org';
34479 }
34480
34481 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
34482 $this->io = $io;
34483 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
34484 $this->loader = new ArrayLoader();
34485 if ($rfs && $this->options) {
34486 $rfs = clone $rfs;
34487 $rfs->setOptions($this->options);
34488 }
34489 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
34490 $this->eventDispatcher = $eventDispatcher;
34491 $this->repoConfig = $repoConfig;
34492 }
34493
34494 public function getRepoConfig()
34495 {
34496 return $this->repoConfig;
34497 }
34498
34499 public function setRootAliases(array $rootAliases)
34500 {
34501 $this->rootAliases = $rootAliases;
34502 }
34503
34504
34505
34506
34507 public function findPackage($name, $constraint)
34508 {
34509 if (!$this->hasProviders()) {
34510 return parent::findPackage($name, $constraint);
34511 }
34512
34513 $name = strtolower($name);
34514 if (!$constraint instanceof ConstraintInterface) {
34515 $versionParser = new VersionParser();
34516 $constraint = $versionParser->parseConstraints($constraint);
34517 }
34518
34519 foreach ($this->getProviderNames() as $providerName) {
34520 if ($name === $providerName) {
34521 $packages = $this->whatProvides(new Pool('dev'), $providerName);
34522 foreach ($packages as $package) {
34523 if ($name === $package->getName()) {
34524 $pkgConstraint = new Constraint('==', $package->getVersion());
34525 if ($constraint->matches($pkgConstraint)) {
34526 return $package;
34527 }
34528 }
34529 }
34530 break;
34531 }
34532 }
34533 }
34534
34535
34536
34537
34538 public function findPackages($name, $constraint = null)
34539 {
34540 if (!$this->hasProviders()) {
34541 return parent::findPackages($name, $constraint);
34542 }
34543
34544 $name = strtolower($name);
34545
34546 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
34547 $versionParser = new VersionParser();
34548 $constraint = $versionParser->parseConstraints($constraint);
34549 }
34550
34551 $packages = array();
34552
34553 foreach ($this->getProviderNames() as $providerName) {
34554 if ($name === $providerName) {
34555 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
34556 foreach ($candidates as $package) {
34557 if ($name === $package->getName()) {
34558 $pkgConstraint = new Constraint('==', $package->getVersion());
34559 if (null === $constraint || $constraint->matches($pkgConstraint)) {
34560 $packages[] = $package;
34561 }
34562 }
34563 }
34564 break;
34565 }
34566 }
34567
34568 return $packages;
34569 }
34570
34571 public function getPackages()
34572 {
34573 if ($this->hasProviders()) {
34574 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
34575 }
34576
34577 return parent::getPackages();
34578 }
34579
34580
34581
34582
34583 public function search($query, $mode = 0, $type = null)
34584 {
34585 $this->loadRootServerFile();
34586
34587 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
34588 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
34589
34590 $origin = RemoteFilesystem::getOrigin($url);
34591 $json = $this->rfs->getContents($origin, $url, false);
34592 $search = JsonFile::parseJson($json, $url);
34593
34594 if (empty($search['results'])) {
34595 return array();
34596 }
34597
34598 $results = array();
34599 foreach ($search['results'] as $result) {
34600
34601 if (empty($result['virtual'])) {
34602 $results[] = $result;
34603 }
34604 }
34605
34606 return $results;
34607 }
34608
34609 if ($this->hasProviders()) {
34610 $results = array();
34611 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
34612
34613 foreach ($this->getProviderNames() as $name) {
34614 if (preg_match($regex, $name)) {
34615 $results[] = array('name' => $name);
34616 }
34617 }
34618
34619 return $results;
34620 }
34621
34622 return parent::search($query, $mode);
34623 }
34624
34625 public function getProviderNames()
34626 {
34627 $this->loadRootServerFile();
34628
34629 if (null === $this->providerListing) {
34630 $this->loadProviderListings($this->loadRootServerFile());
34631 }
34632
34633 if ($this->hasPartialPackages) {
34634 if (null === $this->partialPackagesByName) {
34635 $this->initializePartialPackages();
34636 }
34637
34638 return array_keys($this->partialPackagesByName);
34639 }
34640
34641 if ($this->lazyProvidersUrl) {
34642
34643 return array();
34644 }
34645
34646 if ($this->providersUrl) {
34647 return array_keys($this->providerListing);
34648 }
34649
34650 return array();
34651 }
34652
34653 protected function configurePackageTransportOptions(PackageInterface $package)
34654 {
34655 foreach ($package->getDistUrls() as $url) {
34656 if (strpos($url, $this->baseUrl) === 0) {
34657 $package->setTransportOptions($this->options);
34658
34659 return;
34660 }
34661 }
34662 }
34663
34664 public function hasProviders()
34665 {
34666 $this->loadRootServerFile();
34667
34668 return $this->hasProviders;
34669 }
34670
34671 public function resetPackageIds()
34672 {
34673 foreach ($this->providersByUid as $package) {
34674 if ($package instanceof AliasPackage) {
34675 $package->getAliasOf()->setId(-1);
34676 }
34677 $package->setId(-1);
34678 }
34679 }
34680
34681
34682
34683
34684
34685
34686
34687 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
34688 {
34689 if (isset($this->providers[$name]) && !$bypassFilters) {
34690 return $this->providers[$name];
34691 }
34692
34693 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
34694 $this->initializePartialPackages();
34695 }
34696
34697 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
34698
34699 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
34700 return array();
34701 }
34702
34703 if (null === $this->providerListing) {
34704 $this->loadProviderListings($this->loadRootServerFile());
34705 }
34706
34707 $useLastModifiedCheck = false;
34708 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
34709 $hash = null;
34710 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
34711 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
34712 $useLastModifiedCheck = true;
34713 } elseif ($this->providersUrl) {
34714
34715 if (!isset($this->providerListing[$name])) {
34716 return array();
34717 }
34718
34719 $hash = $this->providerListing[$name]['sha256'];
34720 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
34721 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
34722 } else {
34723 return array();
34724 }
34725
34726 $packages = null;
34727 if ($cacheKey) {
34728 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
34729 $packages = json_decode($this->cache->read($cacheKey), true);
34730 } elseif ($useLastModifiedCheck) {
34731 if ($contents = $this->cache->read($cacheKey)) {
34732 $contents = json_decode($contents, true);
34733 if (isset($contents['last-modified'])) {
34734 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
34735 if (true === $response) {
34736 $packages = $contents;
34737 } elseif ($response) {
34738 $packages = $response;
34739 }
34740 }
34741 }
34742 }
34743 }
34744
34745 if (!$packages) {
34746 try {
34747 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
34748 } catch (TransportException $e) {
34749
34750 if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
34751 $packages = array('packages' => array());
34752 } else {
34753 throw $e;
34754 }
34755 }
34756 }
34757
34758 $loadingPartialPackage = false;
34759 } else {
34760 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
34761 $loadingPartialPackage = true;
34762 }
34763
34764 $this->providers[$name] = array();
34765 foreach ($packages['packages'] as $versions) {
34766 foreach ($versions as $version) {
34767 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
34768 continue;
34769 }
34770
34771
34772 if (isset($this->providersByUid[$version['uid']])) {
34773
34774 if (!isset($this->providers[$name][$version['uid']])) {
34775
34776 if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
34777 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
34778 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
34779 } else {
34780 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
34781 }
34782
34783 if (isset($this->providersByUid[$version['uid'].'-root'])) {
34784 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
34785 }
34786 }
34787 } else {
34788 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
34789 continue;
34790 }
34791
34792
34793 $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
34794 $package->setRepository($this);
34795
34796 if ($package instanceof AliasPackage) {
34797 $aliased = $package->getAliasOf();
34798 $aliased->setRepository($this);
34799
34800 $this->providers[$name][$version['uid']] = $aliased;
34801 $this->providers[$name][$version['uid'].'-alias'] = $package;
34802
34803
34804 $this->providersByUid[$version['uid']] = $package;
34805 } else {
34806 $this->providers[$name][$version['uid']] = $package;
34807 $this->providersByUid[$version['uid']] = $package;
34808 }
34809
34810
34811 unset($rootAliasData);
34812
34813 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
34814 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
34815 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
34816 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
34817 }
34818
34819 if (isset($rootAliasData)) {
34820 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
34821 $alias->setRepository($this);
34822
34823 $this->providers[$name][$version['uid'].'-root'] = $alias;
34824 $this->providersByUid[$version['uid'].'-root'] = $alias;
34825 }
34826 }
34827 }
34828 }
34829
34830 $result = $this->providers[$name];
34831
34832
34833
34834 if ($bypassFilters) {
34835 foreach ($this->providers[$name] as $uid => $provider) {
34836 unset($this->providersByUid[$uid]);
34837 }
34838 unset($this->providers[$name]);
34839 }
34840
34841 return $result;
34842 }
34843
34844
34845
34846
34847 protected function initialize()
34848 {
34849 parent::initialize();
34850
34851 $repoData = $this->loadDataFromServer();
34852
34853 foreach ($repoData as $package) {
34854 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
34855 }
34856 }
34857
34858
34859
34860
34861
34862
34863 public function addPackage(PackageInterface $package)
34864 {
34865 parent::addPackage($package);
34866 $this->configurePackageTransportOptions($package);
34867 }
34868
34869 protected function loadRootServerFile()
34870 {
34871 if (null !== $this->rootData) {
34872 return $this->rootData;
34873 }
34874
34875 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
34876 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
34877 }
34878
34879 $jsonUrlParts = parse_url($this->url);
34880
34881 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
34882 $jsonUrl = $this->url;
34883 } else {
34884 $jsonUrl = $this->url . '/packages.json';
34885 }
34886
34887 $data = $this->fetchFile($jsonUrl, 'packages.json');
34888
34889 if (!empty($data['notify-batch'])) {
34890 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
34891 } elseif (!empty($data['notify'])) {
34892 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
34893 }
34894
34895 if (!empty($data['search'])) {
34896 $this->searchUrl = $this->canonicalizeUrl($data['search']);
34897 }
34898
34899 if (!empty($data['mirrors'])) {
34900 foreach ($data['mirrors'] as $mirror) {
34901 if (!empty($mirror['git-url'])) {
34902 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
34903 }
34904 if (!empty($mirror['hg-url'])) {
34905 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
34906 }
34907 if (!empty($mirror['dist-url'])) {
34908 $this->distMirrors[] = array(
34909 'url' => $this->canonicalizeUrl($mirror['dist-url']),
34910 'preferred' => !empty($mirror['preferred']),
34911 );
34912 }
34913 }
34914 }
34915
34916 if (!empty($data['providers-lazy-url'])) {
34917 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
34918 $this->hasProviders = true;
34919
34920 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
34921 }
34922
34923 if ($this->allowSslDowngrade) {
34924 $this->url = str_replace('https://', 'http://', $this->url);
34925 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
34926 }
34927
34928 if (!empty($data['providers-url'])) {
34929 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
34930 $this->hasProviders = true;
34931 }
34932
34933 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
34934 $this->hasProviders = true;
34935 }
34936
34937
34938 if (preg_match('{^https?://repo\.packagist\.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
34939 $this->url = 'https://repo.packagist.org';
34940 $this->baseUrl = 'https://repo.packagist.org';
34941 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://repo.packagist.org/p/%package%.json');
34942 $this->providersUrl = null;
34943 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
34944 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
34945 $this->providersUrl = null;
34946 }
34947
34948 return $this->rootData = $data;
34949 }
34950
34951 protected function canonicalizeUrl($url)
34952 {
34953 if ('/' === $url[0]) {
34954 if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) {
34955 return $matches[0] . $url;
34956 }
34957
34958 return $this->url;
34959 }
34960
34961 return $url;
34962 }
34963
34964 protected function loadDataFromServer()
34965 {
34966 $data = $this->loadRootServerFile();
34967
34968 return $this->loadIncludes($data);
34969 }
34970
34971 protected function loadProviderListings($data)
34972 {
34973 if (isset($data['providers'])) {
34974 if (!is_array($this->providerListing)) {
34975 $this->providerListing = array();
34976 }
34977 $this->providerListing = array_merge($this->providerListing, $data['providers']);
34978 }
34979
34980 if ($this->providersUrl && isset($data['provider-includes'])) {
34981 $includes = $data['provider-includes'];
34982 foreach ($includes as $include => $metadata) {
34983 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
34984 $cacheKey = str_replace(array('%hash%','$'), '', $include);
34985 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
34986 $includedData = json_decode($this->cache->read($cacheKey), true);
34987 } else {
34988 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
34989 }
34990
34991 $this->loadProviderListings($includedData);
34992 }
34993 }
34994 }
34995
34996 protected function loadIncludes($data)
34997 {
34998 $packages = array();
34999
35000
35001 if (!isset($data['packages']) && !isset($data['includes'])) {
35002 foreach ($data as $pkg) {
35003 foreach ($pkg['versions'] as $metadata) {
35004 $packages[] = $metadata;
35005 }
35006 }
35007
35008 return $packages;
35009 }
35010
35011 if (isset($data['packages'])) {
35012 foreach ($data['packages'] as $package => $versions) {
35013 foreach ($versions as $version => $metadata) {
35014 $packages[] = $metadata;
35015 }
35016 }
35017 }
35018
35019 if (isset($data['includes'])) {
35020 foreach ($data['includes'] as $include => $metadata) {
35021 if (isset($metadata['sha1']) && $this->cache->sha1($include) === $metadata['sha1']) {
35022 $includedData = json_decode($this->cache->read($include), true);
35023 } else {
35024 $includedData = $this->fetchFile($include);
35025 }
35026 $packages = array_merge($packages, $this->loadIncludes($includedData));
35027 }
35028 }
35029
35030 return $packages;
35031 }
35032
35033 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
35034 {
35035 try {
35036 if (!isset($data['notification-url'])) {
35037 $data['notification-url'] = $this->notifyUrl;
35038 }
35039
35040 $package = $this->loader->load($data, $class);
35041 if (isset($this->sourceMirrors[$package->getSourceType()])) {
35042 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
35043 }
35044 $package->setDistMirrors($this->distMirrors);
35045 $this->configurePackageTransportOptions($package);
35046
35047 return $package;
35048 } catch (\Exception $e) {
35049 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);
35050 }
35051 }
35052
35053 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
35054 {
35055 if (null === $cacheKey) {
35056 $cacheKey = $filename;
35057 $filename = $this->baseUrl.'/'.$filename;
35058 }
35059
35060
35061 if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
35062 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
35063 }
35064
35065 $retries = 3;
35066 while ($retries--) {
35067 try {
35068 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
35069 if ($this->eventDispatcher) {
35070 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
35071 }
35072
35073 $origin = RemoteFilesystem::getOrigin($filename);
35074 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
35075
35076 $json = $rfs->getContents($origin, $filename, false);
35077 if ($sha256 && $sha256 !== hash('sha256', $json)) {
35078
35079 if ($this->allowSslDowngrade) {
35080 $this->url = str_replace('http://', 'https://', $this->url);
35081 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
35082 $filename = str_replace('http://', 'https://', $filename);
35083 }
35084
35085 if ($retries) {
35086 usleep(100000);
35087
35088 continue;
35089 }
35090
35091
35092 throw new RepositorySecurityException('The contents of '.$filename.' do not match its signature. This could indicate a man-in-the-middle attack or e.g. antivirus software corrupting files. Try running composer again and report this if you think it is a mistake.');
35093 }
35094
35095 $data = JsonFile::parseJson($json, $filename);
35096 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
35097
35098 if ($cacheKey) {
35099 if ($storeLastModifiedTime) {
35100 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
35101 if ($lastModifiedDate) {
35102 $data['last-modified'] = $lastModifiedDate;
35103 $json = json_encode($data);
35104 }
35105 }
35106 $this->cache->write($cacheKey, $json);
35107 }
35108
35109 break;
35110 } catch (\Exception $e) {
35111 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
35112 throw $e;
35113 }
35114
35115 if ($retries) {
35116 usleep(100000);
35117 continue;
35118 }
35119
35120 if ($e instanceof RepositorySecurityException) {
35121 throw $e;
35122 }
35123
35124 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
35125 if (!$this->degradedMode) {
35126 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
35127 $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>');
35128 }
35129 $this->degradedMode = true;
35130 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
35131
35132 break;
35133 }
35134
35135 throw $e;
35136 }
35137 }
35138
35139 return $data;
35140 }
35141
35142 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
35143 {
35144 $retries = 3;
35145 while ($retries--) {
35146 try {
35147 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
35148 if ($this->eventDispatcher) {
35149 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
35150 }
35151
35152 $origin = RemoteFilesystem::getOrigin($filename);
35153 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
35154 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
35155 $json = $rfs->getContents($origin, $filename, false, $options);
35156 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
35157 return true;
35158 }
35159
35160 $data = JsonFile::parseJson($json, $filename);
35161 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
35162
35163 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
35164 if ($lastModifiedDate) {
35165 $data['last-modified'] = $lastModifiedDate;
35166 $json = json_encode($data);
35167 }
35168 $this->cache->write($cacheKey, $json);
35169
35170 return $data;
35171 } catch (\Exception $e) {
35172 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
35173 throw $e;
35174 }
35175
35176 if ($retries) {
35177 usleep(100000);
35178 continue;
35179 }
35180
35181 if (!$this->degradedMode) {
35182 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
35183 $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>');
35184 }
35185 $this->degradedMode = true;
35186
35187 return true;
35188 }
35189 }
35190 }
35191
35192
35193
35194
35195
35196
35197 private function initializePartialPackages()
35198 {
35199 $rootData = $this->loadRootServerFile();
35200
35201 $this->partialPackagesByName = array();
35202 foreach ($rootData['packages'] as $package => $versions) {
35203 $package = strtolower($package);
35204 foreach ($versions as $version) {
35205 $this->partialPackagesByName[$package][] = $version;
35206 if (!empty($version['provide']) && is_array($version['provide'])) {
35207 foreach ($version['provide'] as $provided => $providedVersion) {
35208 $this->partialPackagesByName[strtolower($provided)][] = $version;
35209 }
35210 }
35211 if (!empty($version['replace']) && is_array($version['replace'])) {
35212 foreach ($version['replace'] as $provided => $providedVersion) {
35213 $this->partialPackagesByName[strtolower($provided)][] = $version;
35214 }
35215 }
35216 }
35217 }
35218
35219
35220 $this->rootData = true;
35221 }
35222 }
35223 <?php
35224
35225
35226
35227
35228
35229
35230
35231
35232
35233
35234
35235 namespace Composer\Repository;
35236
35237 use Composer\Package\PackageInterface;
35238
35239
35240
35241
35242
35243
35244 class CompositeRepository extends BaseRepository
35245 {
35246
35247
35248
35249
35250 private $repositories;
35251
35252
35253
35254
35255
35256 public function __construct(array $repositories)
35257 {
35258 $this->repositories = array();
35259 foreach ($repositories as $repo) {
35260 $this->addRepository($repo);
35261 }
35262 }
35263
35264
35265
35266
35267
35268
35269 public function getRepositories()
35270 {
35271 return $this->repositories;
35272 }
35273
35274
35275
35276
35277 public function hasPackage(PackageInterface $package)
35278 {
35279 foreach ($this->repositories as $repository) {
35280
35281 if ($repository->hasPackage($package)) {
35282 return true;
35283 }
35284 }
35285
35286 return false;
35287 }
35288
35289
35290
35291
35292 public function findPackage($name, $constraint)
35293 {
35294 foreach ($this->repositories as $repository) {
35295
35296 $package = $repository->findPackage($name, $constraint);
35297 if (null !== $package) {
35298 return $package;
35299 }
35300 }
35301
35302 return null;
35303 }
35304
35305
35306
35307
35308 public function findPackages($name, $constraint = null)
35309 {
35310 $packages = array();
35311 foreach ($this->repositories as $repository) {
35312
35313 $packages[] = $repository->findPackages($name, $constraint);
35314 }
35315
35316 return $packages ? call_user_func_array('array_merge', $packages) : array();
35317 }
35318
35319
35320
35321
35322 public function search($query, $mode = 0, $type = null)
35323 {
35324 $matches = array();
35325 foreach ($this->repositories as $repository) {
35326
35327 $matches[] = $repository->search($query, $mode, $type);
35328 }
35329
35330 return $matches ? call_user_func_array('array_merge', $matches) : array();
35331 }
35332
35333
35334
35335
35336 public function getPackages()
35337 {
35338 $packages = array();
35339 foreach ($this->repositories as $repository) {
35340
35341 $packages[] = $repository->getPackages();
35342 }
35343
35344 return $packages ? call_user_func_array('array_merge', $packages) : array();
35345 }
35346
35347
35348
35349
35350 public function removePackage(PackageInterface $package)
35351 {
35352 foreach ($this->repositories as $repository) {
35353
35354 $repository->removePackage($package);
35355 }
35356 }
35357
35358
35359
35360
35361 public function count()
35362 {
35363 $total = 0;
35364 foreach ($this->repositories as $repository) {
35365
35366 $total += $repository->count();
35367 }
35368
35369 return $total;
35370 }
35371
35372
35373
35374
35375
35376 public function addRepository(RepositoryInterface $repository)
35377 {
35378 if ($repository instanceof self) {
35379 foreach ($repository->getRepositories() as $repo) {
35380 $this->addRepository($repo);
35381 }
35382 } else {
35383 $this->repositories[] = $repository;
35384 }
35385 }
35386 }
35387 <?php
35388
35389
35390
35391
35392
35393
35394
35395
35396
35397
35398
35399 namespace Composer\Repository;
35400
35401
35402
35403
35404
35405
35406 interface ConfigurableRepositoryInterface
35407 {
35408 public function getRepoConfig();
35409 }
35410 <?php
35411
35412
35413
35414
35415
35416
35417
35418
35419
35420
35421
35422 namespace Composer\Repository;
35423
35424 use Composer\Json\JsonFile;
35425 use Composer\Package\Loader\ArrayLoader;
35426 use Composer\Package\Dumper\ArrayDumper;
35427
35428
35429
35430
35431
35432
35433
35434 class FilesystemRepository extends WritableArrayRepository
35435 {
35436 private $file;
35437
35438
35439
35440
35441
35442
35443 public function __construct(JsonFile $repositoryFile)
35444 {
35445 parent::__construct();
35446 $this->file = $repositoryFile;
35447 }
35448
35449
35450
35451
35452 protected function initialize()
35453 {
35454 parent::initialize();
35455
35456 if (!$this->file->exists()) {
35457 return;
35458 }
35459
35460 try {
35461 $packages = $this->file->read();
35462
35463
35464 if (isset($packages['packages'])) {
35465 $packages = $packages['packages'];
35466 }
35467
35468 if (!is_array($packages)) {
35469 throw new \UnexpectedValueException('Could not parse package list from the repository');
35470 }
35471 } catch (\Exception $e) {
35472 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
35473 }
35474
35475 $loader = new ArrayLoader(null, true);
35476 foreach ($packages as $packageData) {
35477 $package = $loader->load($packageData);
35478 $this->addPackage($package);
35479 }
35480 }
35481
35482 public function reload()
35483 {
35484 $this->packages = null;
35485 $this->initialize();
35486 }
35487
35488
35489
35490
35491 public function write()
35492 {
35493 $data = array();
35494 $dumper = new ArrayDumper();
35495
35496 foreach ($this->getCanonicalPackages() as $package) {
35497 $data[] = $dumper->dump($package);
35498 }
35499
35500 usort($data, function ($a, $b) {
35501 return strcmp($a['name'], $b['name']);
35502 });
35503
35504 $this->file->write($data);
35505 }
35506 }
35507 <?php
35508
35509
35510
35511
35512
35513
35514
35515
35516
35517
35518
35519 namespace Composer\Repository;
35520
35521
35522
35523
35524
35525
35526
35527
35528 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
35529 {
35530 }
35531 <?php
35532
35533
35534
35535
35536
35537
35538
35539
35540
35541
35542
35543 namespace Composer\Repository;
35544
35545
35546
35547
35548
35549
35550 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
35551 {
35552 }
35553 <?php
35554
35555
35556
35557
35558
35559
35560
35561
35562
35563
35564
35565 namespace Composer\Repository;
35566
35567
35568
35569
35570
35571
35572
35573
35574 interface InstalledRepositoryInterface extends WritableRepositoryInterface
35575 {
35576 }
35577 <?php
35578
35579
35580
35581
35582
35583
35584
35585
35586
35587
35588
35589 namespace Composer\Repository;
35590
35591
35592
35593
35594
35595
35596 class InvalidRepositoryException extends \Exception
35597 {
35598 }
35599 <?php
35600
35601
35602
35603
35604
35605
35606
35607
35608
35609
35610
35611 namespace Composer\Repository;
35612
35613 use Composer\Package\Loader\ArrayLoader;
35614 use Composer\Package\Loader\ValidatingArrayLoader;
35615
35616
35617
35618
35619
35620
35621 class PackageRepository extends ArrayRepository
35622 {
35623 private $config;
35624
35625
35626
35627
35628
35629
35630 public function __construct(array $config)
35631 {
35632 parent::__construct();
35633 $this->config = $config['package'];
35634
35635
35636 if (!is_numeric(key($this->config))) {
35637 $this->config = array($this->config);
35638 }
35639 }
35640
35641
35642
35643
35644 protected function initialize()
35645 {
35646 parent::initialize();
35647
35648 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
35649 foreach ($this->config as $package) {
35650 try {
35651 $package = $loader->load($package);
35652 } catch (\Exception $e) {
35653 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
35654 }
35655
35656 $this->addPackage($package);
35657 }
35658 }
35659 }
35660 <?php
35661
35662
35663
35664
35665
35666
35667
35668
35669
35670
35671
35672 namespace Composer\Repository;
35673
35674 use Composer\Config;
35675 use Composer\IO\IOInterface;
35676 use Composer\Json\JsonFile;
35677 use Composer\Package\Loader\ArrayLoader;
35678 use Composer\Package\Version\VersionGuesser;
35679 use Composer\Package\Version\VersionParser;
35680 use Composer\Util\Platform;
35681 use Composer\Util\ProcessExecutor;
35682 use Composer\Util\Filesystem;
35683 use Composer\Util\Git as GitUtil;
35684
35685
35686
35687
35688
35689
35690
35691
35692
35693
35694
35695
35696
35697
35698
35699
35700
35701
35702
35703
35704
35705
35706
35707
35708
35709
35710
35711
35712
35713
35714
35715
35716
35717
35718
35719
35720 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
35721 {
35722
35723
35724
35725 private $loader;
35726
35727
35728
35729
35730 private $versionGuesser;
35731
35732
35733
35734
35735 private $url;
35736
35737
35738
35739
35740 private $repoConfig;
35741
35742
35743
35744
35745 private $process;
35746
35747
35748
35749
35750 private $options;
35751
35752
35753
35754
35755
35756
35757
35758
35759 public function __construct(array $repoConfig, IOInterface $io, Config $config)
35760 {
35761 if (!isset($repoConfig['url'])) {
35762 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
35763 }
35764
35765 $this->loader = new ArrayLoader(null, true);
35766 $this->url = Platform::expandPath($repoConfig['url']);
35767 $this->process = new ProcessExecutor($io);
35768 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
35769 $this->repoConfig = $repoConfig;
35770 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
35771 if (!isset($this->options['relative'])) {
35772 $filesystem = new Filesystem();
35773 $this->options['relative'] = !$filesystem->isAbsolutePath($this->url);
35774 }
35775
35776 parent::__construct();
35777 }
35778
35779 public function getRepoConfig()
35780 {
35781 return $this->repoConfig;
35782 }
35783
35784
35785
35786
35787
35788
35789 protected function initialize()
35790 {
35791 parent::initialize();
35792
35793 $urlMatches = $this->getUrlMatches();
35794
35795 if (empty($urlMatches)) {
35796 if (preg_match('{[*{}]}', $this->url)) {
35797 $url = $this->url;
35798 while (preg_match('{[*{}]}', $url)) {
35799 $url = dirname($url);
35800 }
35801
35802 if (is_dir($url)) {
35803 return;
35804 }
35805 }
35806
35807 throw new \RuntimeException('The `url` supplied for the path (' . $this->url . ') repository does not exist');
35808 }
35809
35810 foreach ($urlMatches as $url) {
35811 $path = realpath($url) . DIRECTORY_SEPARATOR;
35812 $composerFilePath = $path.'composer.json';
35813
35814 if (!file_exists($composerFilePath)) {
35815 continue;
35816 }
35817
35818 $json = file_get_contents($composerFilePath);
35819 $package = JsonFile::parseJson($json, $composerFilePath);
35820 $package['dist'] = array(
35821 'type' => 'path',
35822 'url' => $url,
35823 'reference' => sha1($json . serialize($this->options)),
35824 );
35825 $package['transport-options'] = $this->options;
35826 unset($package['transport-options']['versions']);
35827
35828
35829 if (isset($package['name'], $this->options['versions'][$package['name']])) {
35830 $package['version'] = $this->options['versions'][$package['name']];
35831 }
35832
35833
35834 if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
35835 if (
35836 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
35837 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
35838 && $ref1 === $ref2
35839 ) {
35840 $package['version'] = $rootVersion;
35841 }
35842 }
35843
35844 $output = '';
35845 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H'.GitUtil::getNoShowSignatureFlag($this->process), $output, $path)) {
35846 $package['dist']['reference'] = trim($output);
35847 }
35848
35849 if (!isset($package['version'])) {
35850 $versionData = $this->versionGuesser->guessVersion($package, $path);
35851 if (is_array($versionData) && $versionData['pretty_version']) {
35852
35853 if (!empty($versionData['feature_pretty_version'])) {
35854 $package['version'] = $versionData['feature_pretty_version'];
35855 $this->addPackage($this->loader->load($package));
35856 }
35857
35858 $package['version'] = $versionData['pretty_version'];
35859 } else {
35860 $package['version'] = 'dev-master';
35861 }
35862 }
35863
35864 $package = $this->loader->load($package);
35865 $this->addPackage($package);
35866 }
35867 }
35868
35869
35870
35871
35872
35873
35874 private function getUrlMatches()
35875 {
35876 $flags = GLOB_MARK | GLOB_ONLYDIR;
35877
35878 if (defined('GLOB_BRACE')) {
35879 $flags |= GLOB_BRACE;
35880 } elseif (strpos($this->url, '{') !== false || strpos($this->url, '}') !== false) {
35881 throw new \RuntimeException('The operating system does not support GLOB_BRACE which is required for the url '. $this->url);
35882 }
35883
35884
35885 return array_map(function ($val) {
35886 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
35887 }, glob($this->url, $flags));
35888 }
35889 }
35890 <?php
35891
35892
35893
35894
35895
35896
35897
35898
35899
35900
35901
35902 namespace Composer\Repository\Pear;
35903
35904 use Composer\Util\RemoteFilesystem;
35905
35906
35907
35908
35909
35910
35911
35912
35913 abstract class BaseChannelReader
35914 {
35915
35916
35917
35918 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
35919 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
35920 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
35921 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
35922 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
35923 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
35924
35925
35926 private $rfs;
35927
35928 protected function __construct(RemoteFilesystem $rfs)
35929 {
35930 $this->rfs = $rfs;
35931 }
35932
35933
35934
35935
35936
35937
35938
35939
35940
35941 protected function requestContent($origin, $path)
35942 {
35943 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
35944 $content = $this->rfs->getContents($origin, $url, false);
35945 if (!$content) {
35946 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
35947 }
35948
35949 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
35950 }
35951
35952
35953
35954
35955
35956
35957
35958
35959
35960 protected function requestXml($origin, $path)
35961 {
35962
35963 $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
35964
35965 if (false === $xml) {
35966 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
35967 }
35968
35969 return $xml;
35970 }
35971 }
35972 <?php
35973
35974
35975
35976
35977
35978
35979
35980
35981
35982
35983
35984 namespace Composer\Repository\Pear;
35985
35986
35987
35988
35989
35990
35991 class ChannelInfo
35992 {
35993 private $name;
35994 private $alias;
35995 private $packages;
35996
35997
35998
35999
36000
36001
36002 public function __construct($name, $alias, array $packages)
36003 {
36004 $this->name = $name;
36005 $this->alias = $alias;
36006 $this->packages = $packages;
36007 }
36008
36009
36010
36011
36012
36013
36014 public function getName()
36015 {
36016 return $this->name;
36017 }
36018
36019
36020
36021
36022
36023
36024 public function getAlias()
36025 {
36026 return $this->alias;
36027 }
36028
36029
36030
36031
36032
36033
36034 public function getPackages()
36035 {
36036 return $this->packages;
36037 }
36038 }
36039 <?php
36040
36041
36042
36043
36044
36045
36046
36047
36048
36049
36050
36051 namespace Composer\Repository\Pear;
36052
36053 use Composer\Util\RemoteFilesystem;
36054
36055
36056
36057
36058
36059
36060
36061
36062 class ChannelReader extends BaseChannelReader
36063 {
36064
36065 private $readerMap;
36066
36067 public function __construct(RemoteFilesystem $rfs)
36068 {
36069 parent::__construct($rfs);
36070
36071 $rest10reader = new ChannelRest10Reader($rfs);
36072 $rest11reader = new ChannelRest11Reader($rfs);
36073
36074 $this->readerMap = array(
36075 'REST1.3' => $rest11reader,
36076 'REST1.2' => $rest11reader,
36077 'REST1.1' => $rest11reader,
36078 'REST1.0' => $rest10reader,
36079 );
36080 }
36081
36082
36083
36084
36085
36086
36087
36088
36089 public function read($url)
36090 {
36091 $xml = $this->requestXml($url, "/channel.xml");
36092
36093 $channelName = (string) $xml->name;
36094 $channelAlias = (string) $xml->suggestedalias;
36095
36096 $supportedVersions = array_keys($this->readerMap);
36097 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
36098 if (!$selectedRestVersion) {
36099 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
36100 }
36101
36102 $reader = $this->readerMap[$selectedRestVersion['version']];
36103 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
36104
36105 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
36106 }
36107
36108
36109
36110
36111
36112
36113
36114
36115 private function selectRestVersion($channelXml, $supportedVersions)
36116 {
36117 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
36118
36119 foreach ($supportedVersions as $version) {
36120 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
36121 $testResult = $channelXml->xpath($xpathTest);
36122
36123 foreach ($testResult as $result) {
36124
36125 $result = (string) $result;
36126 if (preg_match('{^https://}i', $result)) {
36127 return array('version' => $version, 'baseUrl' => $result);
36128 }
36129 }
36130
36131
36132 if (count($testResult) > 0) {
36133 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
36134 }
36135 }
36136
36137 return null;
36138 }
36139 }
36140 <?php
36141
36142
36143
36144
36145
36146
36147
36148
36149
36150
36151
36152 namespace Composer\Repository\Pear;
36153
36154 use Composer\Downloader\TransportException;
36155
36156
36157
36158
36159
36160
36161
36162
36163
36164
36165
36166
36167 class ChannelRest10Reader extends BaseChannelReader
36168 {
36169 private $dependencyReader;
36170
36171 public function __construct($rfs)
36172 {
36173 parent::__construct($rfs);
36174
36175 $this->dependencyReader = new PackageDependencyParser();
36176 }
36177
36178
36179
36180
36181
36182
36183
36184
36185 public function read($baseUrl)
36186 {
36187 return $this->readPackages($baseUrl);
36188 }
36189
36190
36191
36192
36193
36194
36195
36196
36197 private function readPackages($baseUrl)
36198 {
36199 $result = array();
36200
36201 $xmlPath = '/p/packages.xml';
36202 $xml = $this->requestXml($baseUrl, $xmlPath);
36203 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
36204 foreach ($xml->xpath('ns:p') as $node) {
36205 $packageName = (string) $node;
36206 $packageInfo = $this->readPackage($baseUrl, $packageName);
36207 $result[] = $packageInfo;
36208 }
36209
36210 return $result;
36211 }
36212
36213
36214
36215
36216
36217
36218
36219
36220
36221 private function readPackage($baseUrl, $packageName)
36222 {
36223 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
36224 $xml = $this->requestXml($baseUrl, $xmlPath);
36225 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
36226
36227 $channelName = (string) $xml->c;
36228 $packageName = (string) $xml->n;
36229 $license = (string) $xml->l;
36230 $shortDescription = (string) $xml->s;
36231 $description = (string) $xml->d;
36232
36233 return new PackageInfo(
36234 $channelName,
36235 $packageName,
36236 $license,
36237 $shortDescription,
36238 $description,
36239 $this->readPackageReleases($baseUrl, $packageName)
36240 );
36241 }
36242
36243
36244
36245
36246
36247
36248
36249
36250
36251
36252 private function readPackageReleases($baseUrl, $packageName)
36253 {
36254 $result = array();
36255
36256 try {
36257 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
36258 $xml = $this->requestXml($baseUrl, $xmlPath);
36259 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
36260 foreach ($xml->xpath('ns:r') as $node) {
36261 $releaseVersion = (string) $node->v;
36262 $releaseStability = (string) $node->s;
36263
36264 try {
36265 $result[$releaseVersion] = new ReleaseInfo(
36266 $releaseStability,
36267 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
36268 );
36269 } catch (TransportException $exception) {
36270 if ($exception->getCode() != 404) {
36271 throw $exception;
36272 }
36273 }
36274 }
36275 } catch (TransportException $exception) {
36276 if ($exception->getCode() != 404) {
36277 throw $exception;
36278 }
36279 }
36280
36281 return $result;
36282 }
36283
36284
36285
36286
36287
36288
36289
36290
36291
36292
36293 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
36294 {
36295 $dependencyReader = new PackageDependencyParser();
36296
36297 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
36298 $content = $this->requestContent($baseUrl, $depthPath);
36299 $dependencyArray = unserialize($content);
36300
36301 return $dependencyReader->buildDependencyInfo($dependencyArray);
36302 }
36303 }
36304 <?php
36305
36306
36307
36308
36309
36310
36311
36312
36313
36314
36315
36316 namespace Composer\Repository\Pear;
36317
36318
36319
36320
36321
36322
36323
36324
36325
36326
36327 class ChannelRest11Reader extends BaseChannelReader
36328 {
36329 private $dependencyReader;
36330
36331 public function __construct($rfs)
36332 {
36333 parent::__construct($rfs);
36334
36335 $this->dependencyReader = new PackageDependencyParser();
36336 }
36337
36338
36339
36340
36341
36342
36343
36344
36345 public function read($baseUrl)
36346 {
36347 return $this->readChannelPackages($baseUrl);
36348 }
36349
36350
36351
36352
36353
36354
36355
36356
36357 private function readChannelPackages($baseUrl)
36358 {
36359 $result = array();
36360
36361 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
36362 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
36363 foreach ($xml->xpath('ns:c') as $node) {
36364 $categoryName = (string) $node;
36365 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
36366 $result = array_merge($result, $categoryPackages);
36367 }
36368
36369 return $result;
36370 }
36371
36372
36373
36374
36375
36376
36377
36378
36379
36380 private function readCategoryPackages($baseUrl, $categoryName)
36381 {
36382 $result = array();
36383
36384 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
36385 $xml = $this->requestXml($baseUrl, $categoryPath);
36386 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
36387 foreach ($xml->xpath('ns:pi') as $node) {
36388 $packageInfo = $this->parsePackage($node);
36389 $result[] = $packageInfo;
36390 }
36391
36392 return $result;
36393 }
36394
36395
36396
36397
36398
36399
36400
36401 private function parsePackage($packageInfo)
36402 {
36403 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
36404 $channelName = (string) $packageInfo->p->c;
36405 $packageName = (string) $packageInfo->p->n;
36406 $license = (string) $packageInfo->p->l;
36407 $shortDescription = (string) $packageInfo->p->s;
36408 $description = (string) $packageInfo->p->d;
36409
36410 $dependencies = array();
36411 foreach ($packageInfo->xpath('ns:deps') as $node) {
36412 $dependencyVersion = (string) $node->v;
36413 $dependencyArray = unserialize((string) $node->d);
36414
36415 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
36416
36417 $dependencies[$dependencyVersion] = $dependencyInfo;
36418 }
36419
36420 $releases = array();
36421 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
36422 if ($releasesInfo) {
36423 foreach ($releasesInfo as $node) {
36424 $releaseVersion = (string) $node->v;
36425 $releaseStability = (string) $node->s;
36426 $releases[$releaseVersion] = new ReleaseInfo(
36427 $releaseStability,
36428 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
36429 );
36430 }
36431 }
36432
36433 return new PackageInfo(
36434 $channelName,
36435 $packageName,
36436 $license,
36437 $shortDescription,
36438 $description,
36439 $releases
36440 );
36441 }
36442 }
36443 <?php
36444
36445
36446
36447
36448
36449
36450
36451
36452
36453
36454
36455 namespace Composer\Repository\Pear;
36456
36457
36458
36459
36460
36461
36462 class DependencyConstraint
36463 {
36464 private $type;
36465 private $constraint;
36466 private $channelName;
36467 private $packageName;
36468
36469
36470
36471
36472
36473
36474
36475 public function __construct($type, $constraint, $channelName, $packageName)
36476 {
36477 $this->type = $type;
36478 $this->constraint = $constraint;
36479 $this->channelName = $channelName;
36480 $this->packageName = $packageName;
36481 }
36482
36483 public function getChannelName()
36484 {
36485 return $this->channelName;
36486 }
36487
36488 public function getConstraint()
36489 {
36490 return $this->constraint;
36491 }
36492
36493 public function getPackageName()
36494 {
36495 return $this->packageName;
36496 }
36497
36498 public function getType()
36499 {
36500 return $this->type;
36501 }
36502 }
36503 <?php
36504
36505
36506
36507
36508
36509
36510
36511
36512
36513
36514
36515 namespace Composer\Repository\Pear;
36516
36517
36518
36519
36520
36521
36522 class DependencyInfo
36523 {
36524 private $requires;
36525 private $optionals;
36526
36527
36528
36529
36530
36531 public function __construct($requires, $optionals)
36532 {
36533 $this->requires = $requires;
36534 $this->optionals = $optionals;
36535 }
36536
36537
36538
36539
36540 public function getRequires()
36541 {
36542 return $this->requires;
36543 }
36544
36545
36546
36547
36548 public function getOptionals()
36549 {
36550 return $this->optionals;
36551 }
36552 }
36553 <?php
36554
36555
36556
36557
36558
36559
36560
36561
36562
36563
36564
36565 namespace Composer\Repository\Pear;
36566
36567
36568
36569
36570
36571
36572 class PackageDependencyParser
36573 {
36574
36575
36576
36577
36578
36579
36580 public function buildDependencyInfo($depArray)
36581 {
36582 if (!is_array($depArray)) {
36583 return new DependencyInfo(array(), array());
36584 }
36585 if (!$this->isHash($depArray)) {
36586 return new DependencyInfo($this->buildDependency10Info($depArray), array());
36587 }
36588
36589 return $this->buildDependency20Info($depArray);
36590 }
36591
36592
36593
36594
36595
36596
36597
36598
36599
36600
36601
36602
36603
36604 private function buildDependency10Info($depArray)
36605 {
36606 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
36607
36608 $result = array();
36609
36610 foreach ($depArray as $depItem) {
36611 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
36612
36613 continue;
36614 }
36615
36616 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
36617 ? 'optional'
36618 : 'required';
36619 $depType = 'not' == $depItem['rel']
36620 ? 'conflicts'
36621 : $depType;
36622
36623 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
36624
36625
36626 $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
36627 ? '*'
36628 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
36629
36630 switch ($depItem['type']) {
36631 case 'php':
36632 $depChannelName = 'php';
36633 $depPackageName = '';
36634 break;
36635 case 'pkg':
36636 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
36637 $depPackageName = $depItem['name'];
36638 break;
36639 case 'ext':
36640 $depChannelName = 'ext';
36641 $depPackageName = $depItem['name'];
36642 break;
36643 case 'os':
36644 case 'sapi':
36645 $depChannelName = '';
36646 $depPackageName = '';
36647 break;
36648 default:
36649 $depChannelName = '';
36650 $depPackageName = '';
36651 break;
36652 }
36653
36654 if ('' != $depChannelName) {
36655 $result[] = new DependencyConstraint(
36656 $depType,
36657 $depVersionConstraint,
36658 $depChannelName,
36659 $depPackageName
36660 );
36661 }
36662 }
36663
36664 return $result;
36665 }
36666
36667
36668
36669
36670
36671
36672
36673 private function buildDependency20Info($depArray)
36674 {
36675 $result = array();
36676 $optionals = array();
36677 $defaultOptionals = array();
36678 foreach ($depArray as $depType => $depTypeGroup) {
36679 if (!is_array($depTypeGroup)) {
36680 continue;
36681 }
36682 if ('required' == $depType || 'optional' == $depType) {
36683 foreach ($depTypeGroup as $depItemType => $depItem) {
36684 switch ($depItemType) {
36685 case 'php':
36686 $result[] = new DependencyConstraint(
36687 $depType,
36688 $this->parse20VersionConstraint($depItem),
36689 'php',
36690 ''
36691 );
36692 break;
36693 case 'package':
36694 $deps = $this->buildDepPackageConstraints($depItem, $depType);
36695 $result = array_merge($result, $deps);
36696 break;
36697 case 'extension':
36698 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
36699 $result = array_merge($result, $deps);
36700 break;
36701 case 'subpackage':
36702 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
36703 $defaultOptionals += $deps;
36704 break;
36705 case 'os':
36706 case 'pearinstaller':
36707 break;
36708 default:
36709 break;
36710 }
36711 }
36712 } elseif ('group' == $depType) {
36713 if ($this->isHash($depTypeGroup)) {
36714 $depTypeGroup = array($depTypeGroup);
36715 }
36716
36717 foreach ($depTypeGroup as $depItem) {
36718 $groupName = $depItem['attribs']['name'];
36719 if (!isset($optionals[$groupName])) {
36720 $optionals[$groupName] = array();
36721 }
36722
36723 if (isset($depItem['subpackage'])) {
36724 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
36725 } else {
36726 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
36727 }
36728 }
36729 }
36730 }
36731
36732 if (count($defaultOptionals) > 0) {
36733 $optionals['*'] = $defaultOptionals;
36734 }
36735
36736 return new DependencyInfo($result, $optionals);
36737 }
36738
36739
36740
36741
36742
36743
36744
36745
36746 private function buildDepExtensionConstraints($depItem, $depType)
36747 {
36748 if ($this->isHash($depItem)) {
36749 $depItem = array($depItem);
36750 }
36751
36752 $result = array();
36753 foreach ($depItem as $subDepItem) {
36754 $depChannelName = 'ext';
36755 $depPackageName = $subDepItem['name'];
36756 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
36757
36758 $result[] = new DependencyConstraint(
36759 $depType,
36760 $depVersionConstraint,
36761 $depChannelName,
36762 $depPackageName
36763 );
36764 }
36765
36766 return $result;
36767 }
36768
36769
36770
36771
36772
36773
36774
36775
36776 private function buildDepPackageConstraints($depItem, $depType)
36777 {
36778 if ($this->isHash($depItem)) {
36779 $depItem = array($depItem);
36780 }
36781
36782 $result = array();
36783 foreach ($depItem as $subDepItem) {
36784 if (!array_key_exists('channel', $subDepItem)) {
36785 $subDepItem['channel'] = $subDepItem['uri'];
36786 }
36787 $depChannelName = $subDepItem['channel'];
36788 $depPackageName = $subDepItem['name'];
36789 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
36790 if (isset($subDepItem['conflicts'])) {
36791 $depType = 'conflicts';
36792 }
36793
36794 $result[] = new DependencyConstraint(
36795 $depType,
36796 $depVersionConstraint,
36797 $depChannelName,
36798 $depPackageName
36799 );
36800 }
36801
36802 return $result;
36803 }
36804
36805
36806
36807
36808
36809
36810
36811 private function parse20VersionConstraint(array $data)
36812 {
36813 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
36814
36815 $versions = array();
36816 $values = array_intersect_key($data, $dep20toOperatorMap);
36817 if (0 == count($values)) {
36818 return '*';
36819 }
36820 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
36821 $versions[] = '>' . $this->parseVersion($values['min']);
36822 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
36823 $versions[] = '<' . $this->parseVersion($values['max']);
36824 } else {
36825 foreach ($values as $op => $version) {
36826 if ('exclude' == $op && is_array($version)) {
36827 foreach ($version as $versionPart) {
36828 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
36829 }
36830 } else {
36831 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
36832 }
36833 }
36834 }
36835
36836 return implode(',', $versions);
36837 }
36838
36839
36840
36841
36842
36843
36844
36845 private function parseVersion($version)
36846 {
36847 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
36848 $version = $matches[1]
36849 .(!empty($matches[2]) ? $matches[2] : '.0')
36850 .(!empty($matches[3]) ? $matches[3] : '.0')
36851 .(!empty($matches[4]) ? $matches[4] : '.0');
36852
36853 return $version;
36854 }
36855
36856 return null;
36857 }
36858
36859
36860
36861
36862
36863
36864
36865 private function isHash(array $array)
36866 {
36867 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
36868 }
36869 }
36870 <?php
36871
36872
36873
36874
36875
36876
36877
36878
36879
36880
36881
36882 namespace Composer\Repository\Pear;
36883
36884
36885
36886
36887
36888
36889 class PackageInfo
36890 {
36891 private $channelName;
36892 private $packageName;
36893 private $license;
36894 private $shortDescription;
36895 private $description;
36896 private $releases;
36897
36898
36899
36900
36901
36902
36903
36904
36905
36906 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
36907 {
36908 $this->channelName = $channelName;
36909 $this->packageName = $packageName;
36910 $this->license = $license;
36911 $this->shortDescription = $shortDescription;
36912 $this->description = $description;
36913 $this->releases = $releases;
36914 }
36915
36916
36917
36918
36919 public function getChannelName()
36920 {
36921 return $this->channelName;
36922 }
36923
36924
36925
36926
36927 public function getPackageName()
36928 {
36929 return $this->packageName;
36930 }
36931
36932
36933
36934
36935 public function getDescription()
36936 {
36937 return $this->description;
36938 }
36939
36940
36941
36942
36943 public function getShortDescription()
36944 {
36945 return $this->shortDescription;
36946 }
36947
36948
36949
36950
36951 public function getLicense()
36952 {
36953 return $this->license;
36954 }
36955
36956
36957
36958
36959 public function getReleases()
36960 {
36961 return $this->releases;
36962 }
36963 }
36964 <?php
36965
36966
36967
36968
36969
36970
36971
36972
36973
36974
36975
36976 namespace Composer\Repository\Pear;
36977
36978
36979
36980
36981
36982
36983 class ReleaseInfo
36984 {
36985 private $stability;
36986 private $dependencyInfo;
36987
36988
36989
36990
36991
36992 public function __construct($stability, $dependencyInfo)
36993 {
36994 $this->stability = $stability;
36995 $this->dependencyInfo = $dependencyInfo;
36996 }
36997
36998
36999
37000
37001 public function getDependencyInfo()
37002 {
37003 return $this->dependencyInfo;
37004 }
37005
37006
37007
37008
37009 public function getStability()
37010 {
37011 return $this->stability;
37012 }
37013 }
37014 <?php
37015
37016
37017
37018
37019
37020
37021
37022
37023
37024
37025
37026 namespace Composer\Repository;
37027
37028 use Composer\IO\IOInterface;
37029 use Composer\Semver\VersionParser as SemverVersionParser;
37030 use Composer\Package\Version\VersionParser;
37031 use Composer\Repository\Pear\ChannelReader;
37032 use Composer\Package\CompletePackage;
37033 use Composer\Repository\Pear\ChannelInfo;
37034 use Composer\EventDispatcher\EventDispatcher;
37035 use Composer\Package\Link;
37036 use Composer\Semver\Constraint\Constraint;
37037 use Composer\Util\RemoteFilesystem;
37038 use Composer\Config;
37039 use Composer\Factory;
37040
37041
37042
37043
37044
37045
37046
37047
37048
37049
37050 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
37051 {
37052 private $url;
37053 private $io;
37054 private $rfs;
37055 private $versionParser;
37056 private $repoConfig;
37057
37058
37059
37060
37061 private $vendorAlias;
37062
37063 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
37064 {
37065 parent::__construct();
37066 if (!preg_match('{^https?://}', $repoConfig['url'])) {
37067 $repoConfig['url'] = 'http://'.$repoConfig['url'];
37068 }
37069
37070 $urlBits = parse_url($repoConfig['url']);
37071 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
37072 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
37073 }
37074
37075 $this->url = rtrim($repoConfig['url'], '/');
37076 $this->io = $io;
37077 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
37078 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
37079 $this->versionParser = new VersionParser();
37080 $this->repoConfig = $repoConfig;
37081 }
37082
37083 public function getRepoConfig()
37084 {
37085 return $this->repoConfig;
37086 }
37087
37088 protected function initialize()
37089 {
37090 parent::initialize();
37091
37092 $this->io->writeError('Initializing PEAR repository '.$this->url);
37093
37094 $reader = new ChannelReader($this->rfs);
37095 try {
37096 $channelInfo = $reader->read($this->url);
37097 } catch (\Exception $e) {
37098 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
37099
37100 return;
37101 }
37102 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
37103 foreach ($packages as $package) {
37104 $this->addPackage($package);
37105 }
37106 }
37107
37108
37109
37110
37111
37112
37113
37114
37115 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
37116 {
37117 $result = array();
37118 foreach ($channelInfo->getPackages() as $packageDefinition) {
37119 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
37120 try {
37121 $normalizedVersion = $versionParser->normalize($version);
37122 } catch (\UnexpectedValueException $e) {
37123 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
37124 continue;
37125 }
37126
37127 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
37128
37129
37130
37131 $urlBits = parse_url($this->url);
37132 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
37133 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
37134
37135 $requires = array();
37136 $suggests = array();
37137 $conflicts = array();
37138 $replaces = array();
37139
37140
37141
37142 if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
37143 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
37144 $aliasConstraint = new Constraint('==', $normalizedVersion);
37145 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
37146 }
37147
37148
37149 if (!empty($this->vendorAlias)
37150 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
37151 ) {
37152 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
37153 $aliasConstraint = new Constraint('==', $normalizedVersion);
37154 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
37155 }
37156
37157 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
37158 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
37159 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
37160 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
37161 switch ($dependencyConstraint->getType()) {
37162 case 'required':
37163 $requires[] = $link;
37164 break;
37165 case 'conflicts':
37166 $conflicts[] = $link;
37167 break;
37168 case 'replaces':
37169 $replaces[] = $link;
37170 break;
37171 }
37172 }
37173
37174 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
37175 foreach ($dependencyConstraints as $dependencyConstraint) {
37176 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
37177 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
37178 }
37179 }
37180
37181 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
37182 $package->setType('pear-library');
37183 $package->setDescription($packageDefinition->getDescription());
37184 $package->setLicense(array($packageDefinition->getLicense()));
37185 $package->setDistType('file');
37186 $package->setDistUrl($distUrl);
37187 $package->setAutoload(array('classmap' => array('')));
37188 $package->setIncludePaths(array('/'));
37189 $package->setRequires($requires);
37190 $package->setConflicts($conflicts);
37191 $package->setSuggests($suggests);
37192 $package->setReplaces($replaces);
37193 $result[] = $package;
37194 }
37195 }
37196
37197 return $result;
37198 }
37199
37200 private function buildComposerPackageName($channelName, $packageName)
37201 {
37202 if ('php' === $channelName) {
37203 return "php";
37204 }
37205 if ('ext' === $channelName) {
37206 return "ext-{$packageName}";
37207 }
37208
37209 return "pear-{$channelName}/{$packageName}";
37210 }
37211 }
37212 <?php
37213
37214
37215
37216
37217
37218
37219
37220
37221
37222
37223
37224 namespace Composer\Repository;
37225
37226 use Composer\Composer;
37227 use Composer\Package\CompletePackage;
37228 use Composer\Package\PackageInterface;
37229 use Composer\Package\Version\VersionParser;
37230 use Composer\Plugin\PluginInterface;
37231 use Composer\Util\ProcessExecutor;
37232 use Composer\Util\Silencer;
37233 use Composer\Util\Platform;
37234 use Composer\XdebugHandler\XdebugHandler;
37235 use Symfony\Component\Process\ExecutableFinder;
37236
37237
37238
37239
37240 class PlatformRepository extends ArrayRepository
37241 {
37242 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-(?:plugin|runtime)-api)$}iD';
37243
37244 private $versionParser;
37245
37246
37247
37248
37249
37250
37251
37252
37253 private $overrides = array();
37254
37255 private $process;
37256
37257 public function __construct(array $packages = array(), array $overrides = array(), ProcessExecutor $process = null)
37258 {
37259 $this->process = $process === null ? (new ProcessExecutor()) : $process;
37260 foreach ($overrides as $name => $version) {
37261 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
37262 }
37263 parent::__construct($packages);
37264 }
37265
37266 protected function initialize()
37267 {
37268 parent::initialize();
37269
37270 $this->versionParser = new VersionParser();
37271
37272
37273
37274 foreach ($this->overrides as $override) {
37275
37276 if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
37277 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
37278 }
37279
37280 $this->addOverriddenPackage($override);
37281 }
37282
37283 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
37284 $version = $this->versionParser->normalize($prettyVersion);
37285 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
37286 $composerPluginApi->setDescription('The Composer Plugin API');
37287 $this->addPackage($composerPluginApi);
37288
37289 $prettyVersion = Composer::RUNTIME_API_VERSION;
37290 $version = $this->versionParser->normalize($prettyVersion);
37291 $composerRuntimeApi = new CompletePackage('composer-runtime-api', $version, $prettyVersion);
37292 $composerRuntimeApi->setDescription('The Composer Runtime API');
37293 $this->addPackage($composerRuntimeApi);
37294
37295 try {
37296 $prettyVersion = PHP_VERSION;
37297 $version = $this->versionParser->normalize($prettyVersion);
37298 } catch (\UnexpectedValueException $e) {
37299 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
37300 $version = $this->versionParser->normalize($prettyVersion);
37301 }
37302
37303 $php = new CompletePackage('php', $version, $prettyVersion);
37304 $php->setDescription('The PHP interpreter');
37305 $this->addPackage($php);
37306
37307 if (PHP_DEBUG) {
37308 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
37309 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
37310 $this->addPackage($phpdebug);
37311 }
37312
37313 if (defined('PHP_ZTS') && PHP_ZTS) {
37314 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
37315 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
37316 $this->addPackage($phpzts);
37317 }
37318
37319 if (PHP_INT_SIZE === 8) {
37320 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
37321 $php64->setDescription('The PHP interpreter, 64bit');
37322 $this->addPackage($php64);
37323 }
37324
37325
37326
37327 if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
37328 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
37329 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
37330 $this->addPackage($phpIpv6);
37331 }
37332
37333 $loadedExtensions = get_loaded_extensions();
37334
37335
37336 foreach ($loadedExtensions as $name) {
37337 if (in_array($name, array('standard', 'Core'))) {
37338 continue;
37339 }
37340
37341 $reflExt = new \ReflectionExtension($name);
37342 $prettyVersion = $reflExt->getVersion();
37343 $this->addExtension($name, $prettyVersion);
37344 }
37345
37346
37347 if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = XdebugHandler::getSkippedVersion())) {
37348 $this->addExtension('xdebug', $prettyVersion);
37349 }
37350
37351
37352
37353
37354 foreach ($loadedExtensions as $name) {
37355 $prettyVersion = null;
37356 $description = 'The '.$name.' PHP library';
37357 switch ($name) {
37358 case 'curl':
37359 $curlVersion = curl_version();
37360 $prettyVersion = $curlVersion['version'];
37361 break;
37362
37363 case 'iconv':
37364 $prettyVersion = ICONV_VERSION;
37365 break;
37366
37367 case 'intl':
37368 $name = 'ICU';
37369 if (defined('INTL_ICU_VERSION')) {
37370 $prettyVersion = INTL_ICU_VERSION;
37371 } else {
37372 $reflector = new \ReflectionExtension('intl');
37373
37374 ob_start();
37375 $reflector->info();
37376 $output = ob_get_clean();
37377
37378 preg_match('/^ICU version => (.*)$/m', $output, $matches);
37379 $prettyVersion = $matches[1];
37380 }
37381
37382 break;
37383
37384 case 'imagick':
37385 $imagick = new \Imagick();
37386 $imageMagickVersion = $imagick->getVersion();
37387
37388
37389 preg_match('/^ImageMagick ([\d.]+)(?:-(\d+))?/', $imageMagickVersion['versionString'], $matches);
37390 if (isset($matches[2])) {
37391 $prettyVersion = "{$matches[1]}.{$matches[2]}";
37392 } else {
37393 $prettyVersion = $matches[1];
37394 }
37395 break;
37396
37397 case 'libxml':
37398 $prettyVersion = LIBXML_DOTTED_VERSION;
37399 break;
37400
37401 case 'openssl':
37402 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
37403 if (empty($match[2])) {
37404 return $match[1];
37405 }
37406
37407
37408
37409
37410 if (!preg_match('{^z*[a-z]$}', $match[2])) {
37411
37412 return 0;
37413 }
37414
37415 $len = strlen($match[2]);
37416 $patchVersion = ($len - 1) * 26; 
37417 $patchVersion += ord($match[2][$len - 1]) - 96;
37418
37419 return $match[1].'.'.$patchVersion;
37420 }, OPENSSL_VERSION_TEXT);
37421
37422 $description = OPENSSL_VERSION_TEXT;
37423 break;
37424
37425 case 'pcre':
37426 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
37427 break;
37428
37429 case 'uuid':
37430 $prettyVersion = phpversion('uuid');
37431 break;
37432
37433 case 'xsl':
37434 $prettyVersion = LIBXSLT_DOTTED_VERSION;
37435 break;
37436
37437 default:
37438
37439 continue 2;
37440 }
37441
37442 try {
37443 $version = $this->versionParser->normalize($prettyVersion);
37444 } catch (\UnexpectedValueException $e) {
37445 continue;
37446 }
37447
37448 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
37449 $lib->setDescription($description);
37450 $this->addPackage($lib);
37451 }
37452
37453 $hhvmVersion = defined('HHVM_VERSION') ? HHVM_VERSION : null;
37454 if ($hhvmVersion === null && !Platform::isWindows()) {
37455 $finder = new ExecutableFinder();
37456 $hhvm = $finder->find('hhvm');
37457 if ($hhvm !== null) {
37458 $exitCode = $this->process->execute(
37459 ProcessExecutor::escape($hhvm).
37460 ' --php -d hhvm.jit=0 -r "echo HHVM_VERSION;" 2>/dev/null',
37461 $hhvmVersion
37462 );
37463 if ($exitCode !== 0) {
37464 $hhvmVersion = null;
37465 }
37466 }
37467 }
37468 if ($hhvmVersion) {
37469 try {
37470 $prettyVersion = $hhvmVersion;
37471 $version = $this->versionParser->normalize($prettyVersion);
37472 } catch (\UnexpectedValueException $e) {
37473 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $hhvmVersion);
37474 $version = $this->versionParser->normalize($prettyVersion);
37475 }
37476
37477 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
37478 $hhvm->setDescription('The HHVM Runtime (64bit)');
37479 $this->addPackage($hhvm);
37480 }
37481 }
37482
37483
37484
37485
37486 public function addPackage(PackageInterface $package)
37487 {
37488
37489 if (isset($this->overrides[$package->getName()])) {
37490 $overrider = $this->findPackage($package->getName(), '*');
37491 if ($package->getVersion() === $overrider->getVersion()) {
37492 $actualText = 'same as actual';
37493 } else {
37494 $actualText = 'actual: '.$package->getPrettyVersion();
37495 }
37496 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
37497
37498 return;
37499 }
37500
37501
37502 if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
37503 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
37504 if ($package->getVersion() === $overrider->getVersion()) {
37505 $actualText = 'same as actual';
37506 } else {
37507 $actualText = 'actual: '.$package->getPrettyVersion();
37508 }
37509 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
37510
37511 return;
37512 }
37513
37514 parent::addPackage($package);
37515 }
37516
37517 private function addOverriddenPackage(array $override, $name = null)
37518 {
37519 $version = $this->versionParser->normalize($override['version']);
37520 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
37521 $package->setDescription('Package overridden via config.platform');
37522 $package->setExtra(array('config.platform' => true));
37523 parent::addPackage($package);
37524
37525 return $package;
37526 }
37527
37528
37529
37530
37531
37532
37533
37534 private function addExtension($name, $prettyVersion)
37535 {
37536 $extraDescription = null;
37537
37538 try {
37539 $version = $this->versionParser->normalize($prettyVersion);
37540 } catch (\UnexpectedValueException $e) {
37541 $extraDescription = ' (actual version: '.$prettyVersion.')';
37542 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
37543 $prettyVersion = $match[1];
37544 } else {
37545 $prettyVersion = '0';
37546 }
37547 $version = $this->versionParser->normalize($prettyVersion);
37548 }
37549
37550 $packageName = $this->buildPackageName($name);
37551 $ext = new CompletePackage($packageName, $version, $prettyVersion);
37552 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
37553 $this->addPackage($ext);
37554 }
37555
37556 private function buildPackageName($name)
37557 {
37558 return 'ext-' . str_replace(' ', '-', $name);
37559 }
37560 }
37561 <?php
37562
37563
37564
37565
37566
37567
37568
37569
37570
37571
37572
37573 namespace Composer\Repository;
37574
37575 use Composer\Factory;
37576 use Composer\IO\IOInterface;
37577 use Composer\Config;
37578 use Composer\EventDispatcher\EventDispatcher;
37579 use Composer\Util\RemoteFilesystem;
37580 use Composer\Json\JsonFile;
37581
37582
37583
37584
37585 class RepositoryFactory
37586 {
37587
37588
37589
37590
37591
37592
37593
37594 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
37595 {
37596 if (0 === strpos($repository, 'http')) {
37597 $repoConfig = array('type' => 'composer', 'url' => $repository);
37598 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
37599 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
37600 $data = $json->read();
37601 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
37602 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
37603 } elseif ($allowFilesystem) {
37604 $repoConfig = array('type' => 'filesystem', 'json' => $json);
37605 } else {
37606 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
37607 }
37608 } elseif ('{' === substr($repository, 0, 1)) {
37609
37610 $repoConfig = JsonFile::parseJson($repository);
37611 } else {
37612 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
37613 }
37614
37615 return $repoConfig;
37616 }
37617
37618
37619
37620
37621
37622
37623
37624
37625 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false, RepositoryManager $rm = null)
37626 {
37627 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
37628
37629 return static::createRepo($io, $config, $repoConfig, $rm);
37630 }
37631
37632
37633
37634
37635
37636
37637
37638 public static function createRepo(IOInterface $io, Config $config, array $repoConfig, RepositoryManager $rm = null)
37639 {
37640 if (!$rm) {
37641 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
37642 }
37643 $repos = static::createRepos($rm, array($repoConfig));
37644
37645 return reset($repos);
37646 }
37647
37648
37649
37650
37651
37652
37653
37654 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
37655 {
37656 if (!$config) {
37657 $config = Factory::createConfig($io);
37658 }
37659 if ($io) {
37660 $io->loadConfiguration($config);
37661 }
37662 if (!$rm) {
37663 if (!$io) {
37664 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
37665 }
37666 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
37667 }
37668
37669 return static::createRepos($rm, $config->getRepositories());
37670 }
37671
37672
37673
37674
37675
37676
37677
37678
37679 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
37680 {
37681 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
37682 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
37683 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
37684 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
37685 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
37686 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
37687 $rm->setRepositoryClass('git-bitbucket', 'Composer\Repository\VcsRepository');
37688 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
37689 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
37690 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
37691 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
37692 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
37693 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
37694 $rm->setRepositoryClass('hg-bitbucket', 'Composer\Repository\VcsRepository');
37695 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
37696 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
37697
37698 return $rm;
37699 }
37700
37701
37702
37703
37704 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
37705 {
37706 $repos = array();
37707
37708 foreach ($repoConfigs as $index => $repo) {
37709 if (is_string($repo)) {
37710 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
37711 }
37712 if (!is_array($repo)) {
37713 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
37714 }
37715 if (!isset($repo['type'])) {
37716 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
37717 }
37718
37719 $name = self::generateRepositoryName($index, $repo, $repos);
37720 if ($repo['type'] === 'filesystem') {
37721 $repos[$name] = new FilesystemRepository($repo['json']);
37722 } else {
37723 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
37724 }
37725 }
37726
37727 return $repos;
37728 }
37729
37730 public static function generateRepositoryName($index, array $repo, array $existingRepos)
37731 {
37732 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
37733 while (isset($existingRepos[$name])) {
37734 $name .= '2';
37735 }
37736
37737 return $name;
37738 }
37739 }
37740 <?php
37741
37742
37743
37744
37745
37746
37747
37748
37749
37750
37751
37752 namespace Composer\Repository;
37753
37754 use Composer\Package\PackageInterface;
37755
37756
37757
37758
37759
37760
37761
37762
37763 interface RepositoryInterface extends \Countable
37764 {
37765 const SEARCH_FULLTEXT = 0;
37766 const SEARCH_NAME = 1;
37767
37768
37769
37770
37771
37772
37773
37774
37775 public function hasPackage(PackageInterface $package);
37776
37777
37778
37779
37780
37781
37782
37783
37784
37785 public function findPackage($name, $constraint);
37786
37787
37788
37789
37790
37791
37792
37793
37794
37795 public function findPackages($name, $constraint = null);
37796
37797
37798
37799
37800
37801
37802 public function getPackages();
37803
37804
37805
37806
37807
37808
37809
37810
37811
37812 public function search($query, $mode = 0);
37813 }
37814 <?php
37815
37816
37817
37818
37819
37820
37821
37822
37823
37824
37825
37826 namespace Composer\Repository;
37827
37828 use Composer\IO\IOInterface;
37829 use Composer\Config;
37830 use Composer\EventDispatcher\EventDispatcher;
37831 use Composer\Package\PackageInterface;
37832 use Composer\Util\RemoteFilesystem;
37833
37834
37835
37836
37837
37838
37839
37840
37841 class RepositoryManager
37842 {
37843 private $localRepository;
37844 private $repositories = array();
37845 private $repositoryClasses = array();
37846 private $io;
37847 private $config;
37848 private $eventDispatcher;
37849 private $rfs;
37850
37851 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
37852 {
37853 $this->io = $io;
37854 $this->config = $config;
37855 $this->eventDispatcher = $eventDispatcher;
37856 $this->rfs = $rfs;
37857 }
37858
37859
37860
37861
37862
37863
37864
37865
37866
37867 public function findPackage($name, $constraint)
37868 {
37869 foreach ($this->repositories as $repository) {
37870
37871 if ($package = $repository->findPackage($name, $constraint)) {
37872 return $package;
37873 }
37874 }
37875
37876 return null;
37877 }
37878
37879
37880
37881
37882
37883
37884
37885
37886
37887 public function findPackages($name, $constraint)
37888 {
37889 $packages = array();
37890
37891 foreach ($this->getRepositories() as $repository) {
37892 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
37893 }
37894
37895 return $packages;
37896 }
37897
37898
37899
37900
37901
37902
37903 public function addRepository(RepositoryInterface $repository)
37904 {
37905 $this->repositories[] = $repository;
37906 }
37907
37908
37909
37910
37911
37912
37913
37914
37915 public function prependRepository(RepositoryInterface $repository)
37916 {
37917 array_unshift($this->repositories, $repository);
37918 }
37919
37920
37921
37922
37923
37924
37925
37926
37927
37928
37929 public function createRepository($type, $config, $name = null)
37930 {
37931 if (!isset($this->repositoryClasses[$type])) {
37932 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
37933 }
37934
37935 if (isset($config['packagist']) && false === $config['packagist']) {
37936 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
37937 }
37938
37939 $class = $this->repositoryClasses[$type];
37940
37941 $reflMethod = new \ReflectionMethod($class, '__construct');
37942 $params = $reflMethod->getParameters();
37943 if (isset($params[4])) {
37944 $paramType = null;
37945 if (\PHP_VERSION_ID >= 70000) {
37946 $reflectionType = $params[4]->getType();
37947 if ($reflectionType) {
37948 $paramType = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string)$reflectionType;
37949 }
37950 } else {
37951 $paramType = $params[4]->getClass() ? $params[4]->getClass()->getName() : null;
37952 }
37953
37954 if ($paramType === 'Composer\Util\RemoteFilesystem') {
37955 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
37956 }
37957 }
37958
37959 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
37960 }
37961
37962
37963
37964
37965
37966
37967
37968 public function setRepositoryClass($type, $class)
37969 {
37970 $this->repositoryClasses[$type] = $class;
37971 }
37972
37973
37974
37975
37976
37977
37978 public function getRepositories()
37979 {
37980 return $this->repositories;
37981 }
37982
37983
37984
37985
37986
37987
37988 public function setLocalRepository(WritableRepositoryInterface $repository)
37989 {
37990 $this->localRepository = $repository;
37991 }
37992
37993
37994
37995
37996
37997
37998 public function getLocalRepository()
37999 {
38000 return $this->localRepository;
38001 }
38002 }
38003 <?php
38004
38005
38006
38007
38008
38009
38010
38011
38012
38013
38014
38015 namespace Composer\Repository;
38016
38017
38018
38019
38020
38021
38022 class RepositorySecurityException extends \Exception
38023 {
38024 }
38025 <?php
38026
38027
38028
38029
38030
38031
38032
38033
38034
38035
38036
38037 namespace Composer\Repository\Vcs;
38038
38039 use Composer\Cache;
38040 use Composer\Downloader\TransportException;
38041 use Composer\Json\JsonFile;
38042 use Composer\Util\Bitbucket;
38043
38044 abstract class BitbucketDriver extends VcsDriver
38045 {
38046
38047 protected $cache;
38048 protected $owner;
38049 protected $repository;
38050 protected $hasIssues;
38051 protected $rootIdentifier;
38052 protected $tags;
38053 protected $branches;
38054 protected $infoCache = array();
38055 protected $branchesUrl = '';
38056 protected $tagsUrl = '';
38057 protected $homeUrl = '';
38058 protected $website = '';
38059 protected $cloneHttpsUrl = '';
38060
38061
38062
38063
38064 protected $fallbackDriver;
38065
38066 protected $vcsType;
38067
38068
38069
38070
38071 public function initialize()
38072 {
38073 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#i', $this->url, $match);
38074 $this->owner = $match[1];
38075 $this->repository = $match[2];
38076 $this->originUrl = 'bitbucket.org';
38077 $this->cache = new Cache(
38078 $this->io,
38079 implode('/', array(
38080 $this->config->get('cache-repo-dir'),
38081 $this->originUrl,
38082 $this->owner,
38083 $this->repository,
38084 ))
38085 );
38086 }
38087
38088
38089
38090
38091 public function getUrl()
38092 {
38093 if ($this->fallbackDriver) {
38094 return $this->fallbackDriver->getUrl();
38095 }
38096
38097 return $this->cloneHttpsUrl;
38098 }
38099
38100
38101
38102
38103
38104
38105
38106 protected function getRepoData()
38107 {
38108 $resource = sprintf(
38109 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
38110 $this->owner,
38111 $this->repository,
38112 http_build_query(
38113 array('fields' => '-project,-owner'),
38114 null,
38115 '&'
38116 )
38117 );
38118
38119 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
38120 if ($this->fallbackDriver) {
38121 return false;
38122 }
38123 $this->parseCloneUrls($repoData['links']['clone']);
38124
38125 $this->hasIssues = !empty($repoData['has_issues']);
38126 $this->branchesUrl = $repoData['links']['branches']['href'];
38127 $this->tagsUrl = $repoData['links']['tags']['href'];
38128 $this->homeUrl = $repoData['links']['html']['href'];
38129 $this->website = $repoData['website'];
38130 $this->vcsType = $repoData['scm'];
38131
38132 return true;
38133 }
38134
38135
38136
38137
38138 public function getComposerInformation($identifier)
38139 {
38140 if ($this->fallbackDriver) {
38141 return $this->fallbackDriver->getComposerInformation($identifier);
38142 }
38143
38144 if (!isset($this->infoCache[$identifier])) {
38145 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
38146 $composer = JsonFile::parseJson($res);
38147 } else {
38148 $composer = $this->getBaseComposerInformation($identifier);
38149
38150 if ($this->shouldCache($identifier)) {
38151 $this->cache->write($identifier, json_encode($composer));
38152 }
38153 }
38154
38155 if ($composer) {
38156
38157 if (!isset($composer['support']['source'])) {
38158 $label = array_search(
38159 $identifier,
38160 $this->getTags()
38161 ) ?: array_search(
38162 $identifier,
38163 $this->getBranches()
38164 ) ?: $identifier;
38165
38166 if (array_key_exists($label, $tags = $this->getTags())) {
38167 $hash = $tags[$label];
38168 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
38169 $hash = $branches[$label];
38170 }
38171
38172 if (! isset($hash)) {
38173 $composer['support']['source'] = sprintf(
38174 'https://%s/%s/%s/src',
38175 $this->originUrl,
38176 $this->owner,
38177 $this->repository
38178 );
38179 } else {
38180 $composer['support']['source'] = sprintf(
38181 'https://%s/%s/%s/src/%s/?at=%s',
38182 $this->originUrl,
38183 $this->owner,
38184 $this->repository,
38185 $hash,
38186 $label
38187 );
38188 }
38189 }
38190 if (!isset($composer['support']['issues']) && $this->hasIssues) {
38191 $composer['support']['issues'] = sprintf(
38192 'https://%s/%s/%s/issues',
38193 $this->originUrl,
38194 $this->owner,
38195 $this->repository
38196 );
38197 }
38198 if (!isset($composer['homepage'])) {
38199 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
38200 }
38201 }
38202
38203 $this->infoCache[$identifier] = $composer;
38204 }
38205
38206 return $this->infoCache[$identifier];
38207 }
38208
38209
38210
38211
38212 public function getFileContent($file, $identifier)
38213 {
38214 if ($this->fallbackDriver) {
38215 return $this->fallbackDriver->getFileContent($file, $identifier);
38216 }
38217
38218 if (strpos($identifier, '/') !== false) {
38219 $branches = $this->getBranches();
38220 if (isset($branches[$identifier])) {
38221 $identifier = $branches[$identifier];
38222 }
38223 }
38224
38225 $resource = sprintf(
38226 'https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s',
38227 $this->owner,
38228 $this->repository,
38229 $identifier,
38230 $file
38231 );
38232
38233 return $this->getContentsWithOAuthCredentials($resource);
38234 }
38235
38236
38237
38238
38239 public function getChangeDate($identifier)
38240 {
38241 if ($this->fallbackDriver) {
38242 return $this->fallbackDriver->getChangeDate($identifier);
38243 }
38244
38245 if (strpos($identifier, '/') !== false) {
38246 $branches = $this->getBranches();
38247 if (isset($branches[$identifier])) {
38248 $identifier = $branches[$identifier];
38249 }
38250 }
38251
38252 $resource = sprintf(
38253 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
38254 $this->owner,
38255 $this->repository,
38256 $identifier
38257 );
38258 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
38259
38260 return new \DateTime($commit['date']);
38261 }
38262
38263
38264
38265
38266 public function getSource($identifier)
38267 {
38268 if ($this->fallbackDriver) {
38269 return $this->fallbackDriver->getSource($identifier);
38270 }
38271
38272 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
38273 }
38274
38275
38276
38277
38278 public function getDist($identifier)
38279 {
38280 if ($this->fallbackDriver) {
38281 return $this->fallbackDriver->getDist($identifier);
38282 }
38283
38284 $url = sprintf(
38285 'https://bitbucket.org/%s/%s/get/%s.zip',
38286 $this->owner,
38287 $this->repository,
38288 $identifier
38289 );
38290
38291 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
38292 }
38293
38294
38295
38296
38297 public function getTags()
38298 {
38299 if ($this->fallbackDriver) {
38300 return $this->fallbackDriver->getTags();
38301 }
38302
38303 if (null === $this->tags) {
38304 $this->tags = array();
38305 $resource = sprintf(
38306 '%s?%s',
38307 $this->tagsUrl,
38308 http_build_query(
38309 array(
38310 'pagelen' => 100,
38311 'fields' => 'values.name,values.target.hash,next',
38312 'sort' => '-target.date',
38313 ),
38314 null,
38315 '&'
38316 )
38317 );
38318 $hasNext = true;
38319 while ($hasNext) {
38320 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
38321 foreach ($tagsData['values'] as $data) {
38322 $this->tags[$data['name']] = $data['target']['hash'];
38323 }
38324 if (empty($tagsData['next'])) {
38325 $hasNext = false;
38326 } else {
38327 $resource = $tagsData['next'];
38328 }
38329 }
38330 if ($this->vcsType === 'hg') {
38331 unset($this->tags['tip']);
38332 }
38333 }
38334
38335 return $this->tags;
38336 }
38337
38338
38339
38340
38341 public function getBranches()
38342 {
38343 if ($this->fallbackDriver) {
38344 return $this->fallbackDriver->getBranches();
38345 }
38346
38347 if (null === $this->branches) {
38348 $this->branches = array();
38349 $resource = sprintf(
38350 '%s?%s',
38351 $this->branchesUrl,
38352 http_build_query(
38353 array(
38354 'pagelen' => 100,
38355 'fields' => 'values.name,values.target.hash,values.heads,next',
38356 'sort' => '-target.date',
38357 ),
38358 null,
38359 '&'
38360 )
38361 );
38362 $hasNext = true;
38363 while ($hasNext) {
38364 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
38365 foreach ($branchData['values'] as $data) {
38366
38367 if ($this->vcsType === 'hg' && empty($data['heads'])) {
38368 continue;
38369 }
38370
38371 $this->branches[$data['name']] = $data['target']['hash'];
38372 }
38373 if (empty($branchData['next'])) {
38374 $hasNext = false;
38375 } else {
38376 $resource = $branchData['next'];
38377 }
38378 }
38379 }
38380
38381 return $this->branches;
38382 }
38383
38384
38385
38386
38387
38388
38389
38390
38391
38392 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
38393 {
38394 try {
38395 return parent::getContents($url);
38396 } catch (TransportException $e) {
38397 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
38398
38399 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
38400 if (!$this->io->hasAuthentication($this->originUrl)
38401 && $bitbucketUtil->authorizeOAuth($this->originUrl)
38402 ) {
38403 return parent::getContents($url);
38404 }
38405
38406 if (!$this->io->isInteractive() && $fetchingRepoData) {
38407 return $this->attemptCloneFallback();
38408 }
38409 }
38410
38411 throw $e;
38412 }
38413 }
38414
38415
38416
38417
38418
38419
38420 abstract protected function generateSshUrl();
38421
38422 protected function attemptCloneFallback()
38423 {
38424 try {
38425 $this->setupFallbackDriver($this->generateSshUrl());
38426 } catch (\RuntimeException $e) {
38427 $this->fallbackDriver = null;
38428
38429 $this->io->writeError(
38430 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
38431 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
38432 );
38433 throw $e;
38434 }
38435 }
38436
38437
38438
38439
38440
38441 abstract protected function setupFallbackDriver($url);
38442
38443
38444
38445
38446
38447 protected function parseCloneUrls(array $cloneLinks)
38448 {
38449 foreach ($cloneLinks as $cloneLink) {
38450 if ($cloneLink['name'] === 'https') {
38451
38452
38453 $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
38454 }
38455 }
38456 }
38457
38458
38459
38460
38461 protected function getMainBranchData()
38462 {
38463 $resource = sprintf(
38464 'https://api.bitbucket.org/2.0/repositories/%s/%s?fields=mainbranch',
38465 $this->owner,
38466 $this->repository
38467 );
38468
38469 $data = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
38470 if (isset($data['mainbranch'])) {
38471 return $data['mainbranch'];
38472 }
38473
38474 return null;
38475 }
38476 }
38477 <?php
38478
38479
38480
38481
38482
38483
38484
38485
38486
38487
38488
38489 namespace Composer\Repository\Vcs;
38490
38491 use Composer\Cache;
38492 use Composer\Config;
38493 use Composer\Util\ProcessExecutor;
38494 use Composer\Util\Filesystem;
38495 use Composer\IO\IOInterface;
38496
38497
38498
38499
38500 class FossilDriver extends VcsDriver
38501 {
38502 protected $tags;
38503 protected $branches;
38504 protected $rootIdentifier;
38505 protected $repoFile;
38506 protected $checkoutDir;
38507 protected $infoCache = array();
38508
38509
38510
38511
38512 public function initialize()
38513 {
38514
38515 $this->checkFossil();
38516
38517
38518 $this->config->prohibitUrlByConfig($this->url, $this->io);
38519
38520
38521
38522 if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
38523 $this->checkoutDir = $this->url;
38524 } else {
38525 if (!Cache::isUsable($this->config->get('cache-repo-dir')) || !Cache::isUsable($this->config->get('cache-vcs-dir'))) {
38526 throw new \RuntimeException('FossilDriver requires a usable cache directory, and it looks like you set it to be disabled');
38527 }
38528
38529 $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url);
38530 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
38531 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
38532
38533 $this->updateLocalRepo();
38534 }
38535
38536 $this->getTags();
38537 $this->getBranches();
38538 }
38539
38540
38541
38542
38543 protected function checkFossil()
38544 {
38545 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
38546 throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
38547 }
38548 }
38549
38550
38551
38552
38553 protected function updateLocalRepo()
38554 {
38555 $fs = new Filesystem();
38556 $fs->ensureDirectoryExists($this->checkoutDir);
38557
38558 if (!is_writable(dirname($this->checkoutDir))) {
38559 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
38560 }
38561
38562
38563 if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
38564 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
38565 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
38566 }
38567 } else {
38568
38569 $fs->removeDirectory($this->checkoutDir);
38570 $fs->remove($this->repoFile);
38571
38572 $fs->ensureDirectoryExists($this->checkoutDir);
38573
38574 if (0 !== $this->process->execute(sprintf('fossil clone -- %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
38575 $output = $this->process->getErrorOutput();
38576
38577 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
38578 }
38579
38580 if (0 !== $this->process->execute(sprintf('fossil open --nested -- %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
38581 $output = $this->process->getErrorOutput();
38582
38583 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
38584 }
38585 }
38586 }
38587
38588
38589
38590
38591 public function getRootIdentifier()
38592 {
38593 if (null === $this->rootIdentifier) {
38594 $this->rootIdentifier = 'trunk';
38595 }
38596
38597 return $this->rootIdentifier;
38598 }
38599
38600
38601
38602
38603 public function getUrl()
38604 {
38605 return $this->url;
38606 }
38607
38608
38609
38610
38611 public function getSource($identifier)
38612 {
38613 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
38614 }
38615
38616
38617
38618
38619 public function getDist($identifier)
38620 {
38621 return null;
38622 }
38623
38624
38625
38626
38627 public function getFileContent($file, $identifier)
38628 {
38629 $command = sprintf('fossil cat -r %s -- %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
38630 $this->process->execute($command, $content, $this->checkoutDir);
38631
38632 if (!trim($content)) {
38633 return null;
38634 }
38635
38636 return $content;
38637 }
38638
38639
38640
38641
38642 public function getChangeDate($identifier)
38643 {
38644 $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir);
38645 list($ckout, $date, $message) = explode(' ', trim($output), 3);
38646
38647 return new \DateTime($date, new \DateTimeZone('UTC'));
38648 }
38649
38650
38651
38652
38653 public function getTags()
38654 {
38655 if (null === $this->tags) {
38656 $tags = array();
38657
38658 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
38659 foreach ($this->process->splitLines($output) as $tag) {
38660 $tags[$tag] = $tag;
38661 }
38662
38663 $this->tags = $tags;
38664 }
38665
38666 return $this->tags;
38667 }
38668
38669
38670
38671
38672 public function getBranches()
38673 {
38674 if (null === $this->branches) {
38675 $branches = array();
38676 $bookmarks = array();
38677
38678 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
38679 foreach ($this->process->splitLines($output) as $branch) {
38680 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
38681 $branches[$branch] = $branch;
38682 }
38683
38684 $this->branches = $branches;
38685 }
38686
38687 return $this->branches;
38688 }
38689
38690
38691
38692
38693 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38694 {
38695 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
38696 return true;
38697 }
38698
38699 if (preg_match('!/fossil/|\.fossil!', $url)) {
38700 return true;
38701 }
38702
38703
38704 if (Filesystem::isLocalPath($url)) {
38705 $url = Filesystem::getPlatformPath($url);
38706 if (!is_dir($url)) {
38707 return false;
38708 }
38709
38710 $process = new ProcessExecutor($io);
38711
38712 if ($process->execute('fossil info', $output, $url) === 0) {
38713 return true;
38714 }
38715 }
38716
38717 return false;
38718 }
38719 }
38720 <?php
38721
38722
38723
38724
38725
38726
38727
38728
38729
38730
38731
38732 namespace Composer\Repository\Vcs;
38733
38734 use Composer\Config;
38735 use Composer\IO\IOInterface;
38736
38737
38738
38739
38740 class GitBitbucketDriver extends BitbucketDriver
38741 {
38742
38743
38744
38745 public function getRootIdentifier()
38746 {
38747 if ($this->fallbackDriver) {
38748 return $this->fallbackDriver->getRootIdentifier();
38749 }
38750
38751 if (null === $this->rootIdentifier) {
38752 if (! $this->getRepoData()) {
38753 return $this->fallbackDriver->getRootIdentifier();
38754 }
38755
38756 if ($this->vcsType !== 'git') {
38757 throw new \RuntimeException(
38758 $this->url.' does not appear to be a git repository, use '.
38759 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
38760 );
38761 }
38762
38763 $mainBranchData = $this->getMainBranchData();
38764 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
38765 }
38766
38767 return $this->rootIdentifier;
38768 }
38769
38770
38771
38772
38773 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38774 {
38775 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#i', $url)) {
38776 return false;
38777 }
38778
38779 if (!extension_loaded('openssl')) {
38780 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
38781
38782 return false;
38783 }
38784
38785 return true;
38786 }
38787
38788
38789
38790
38791 protected function setupFallbackDriver($url)
38792 {
38793 $this->fallbackDriver = new GitDriver(
38794 array('url' => $url),
38795 $this->io,
38796 $this->config,
38797 $this->process,
38798 $this->remoteFilesystem
38799 );
38800 $this->fallbackDriver->initialize();
38801 }
38802
38803
38804
38805
38806 protected function generateSshUrl()
38807 {
38808 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
38809 }
38810 }
38811 <?php
38812
38813
38814
38815
38816
38817
38818
38819
38820
38821
38822
38823 namespace Composer\Repository\Vcs;
38824
38825 use Composer\Util\ProcessExecutor;
38826 use Composer\Util\Filesystem;
38827 use Composer\Util\Git as GitUtil;
38828 use Composer\IO\IOInterface;
38829 use Composer\Cache;
38830 use Composer\Config;
38831
38832
38833
38834
38835 class GitDriver extends VcsDriver
38836 {
38837 protected $cache;
38838 protected $tags;
38839 protected $branches;
38840 protected $rootIdentifier;
38841 protected $repoDir;
38842 protected $infoCache = array();
38843
38844
38845
38846
38847 public function initialize()
38848 {
38849 if (Filesystem::isLocalPath($this->url)) {
38850 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
38851 if (!is_dir($this->url)) {
38852 throw new \RuntimeException('Failed to read package information from '.$this->url.' as the path does not exist');
38853 }
38854 $this->repoDir = $this->url;
38855 $cacheUrl = realpath($this->url);
38856 } else {
38857 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
38858 throw new \RuntimeException('GitDriver requires a usable cache directory, and it looks like you set it to be disabled');
38859 }
38860
38861 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
38862
38863 GitUtil::cleanEnv();
38864
38865 $fs = new Filesystem();
38866 $fs->ensureDirectoryExists(dirname($this->repoDir));
38867
38868 if (!is_writable(dirname($this->repoDir))) {
38869 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
38870 }
38871
38872 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
38873 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.');
38874 }
38875
38876 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
38877 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
38878 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
38879 }
38880
38881 $cacheUrl = $this->url;
38882 }
38883
38884 $this->getTags();
38885 $this->getBranches();
38886
38887 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
38888 }
38889
38890
38891
38892
38893 public function getRootIdentifier()
38894 {
38895 if (null === $this->rootIdentifier) {
38896 $this->rootIdentifier = 'master';
38897
38898
38899 $this->process->execute('git branch --no-color', $output, $this->repoDir);
38900 $branches = $this->process->splitLines($output);
38901 if (!in_array('* master', $branches)) {
38902 foreach ($branches as $branch) {
38903 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
38904 $this->rootIdentifier = $match[1];
38905 break;
38906 }
38907 }
38908 }
38909 }
38910
38911 return $this->rootIdentifier;
38912 }
38913
38914
38915
38916
38917 public function getUrl()
38918 {
38919 return $this->url;
38920 }
38921
38922
38923
38924
38925 public function getSource($identifier)
38926 {
38927 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
38928 }
38929
38930
38931
38932
38933 public function getDist($identifier)
38934 {
38935 return null;
38936 }
38937
38938
38939
38940
38941 public function getFileContent($file, $identifier)
38942 {
38943 if (isset($identifier[0]) && $identifier[0] === '-') {
38944 throw new \RuntimeException('Invalid git identifier detected. Identifier must not start with a -, given: ' . $identifier);
38945 }
38946
38947 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
38948 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
38949
38950 if (!trim($content)) {
38951 return null;
38952 }
38953
38954 return $content;
38955 }
38956
38957
38958
38959
38960 public function getChangeDate($identifier)
38961 {
38962 $this->process->execute(sprintf(
38963 'git -c log.showSignature=false log -1 --format=%%at %s',
38964 ProcessExecutor::escape($identifier)
38965 ), $output, $this->repoDir);
38966
38967 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
38968 }
38969
38970
38971
38972
38973 public function getTags()
38974 {
38975 if (null === $this->tags) {
38976 $this->tags = array();
38977
38978 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
38979 foreach ($output = $this->process->splitLines($output) as $tag) {
38980 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
38981 $this->tags[$match[2]] = $match[1];
38982 }
38983 }
38984 }
38985
38986 return $this->tags;
38987 }
38988
38989
38990
38991
38992 public function getBranches()
38993 {
38994 if (null === $this->branches) {
38995 $branches = array();
38996
38997 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
38998 foreach ($this->process->splitLines($output) as $branch) {
38999 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
39000 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match) && $match[1][0] !== '-') {
39001 $branches[$match[1]] = $match[2];
39002 }
39003 }
39004 }
39005
39006 $this->branches = $branches;
39007 }
39008
39009 return $this->branches;
39010 }
39011
39012
39013
39014
39015 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39016 {
39017 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
39018 return true;
39019 }
39020
39021
39022 if (Filesystem::isLocalPath($url)) {
39023 $url = Filesystem::getPlatformPath($url);
39024 if (!is_dir($url)) {
39025 return false;
39026 }
39027
39028 $process = new ProcessExecutor($io);
39029
39030 if ($process->execute('git tag', $output, $url) === 0) {
39031 return true;
39032 }
39033 }
39034
39035 if (!$deep) {
39036 return false;
39037 }
39038
39039 $gitUtil = new GitUtil($io, $config, new ProcessExecutor($io), new Filesystem());
39040 GitUtil::cleanEnv();
39041
39042 try {
39043 $gitUtil->runCommand(function ($url) {
39044 return 'git ls-remote --heads -- ' . ProcessExecutor::escape($url);
39045 }, $url, sys_get_temp_dir());
39046 } catch (\RuntimeException $e) {
39047 return false;
39048 }
39049
39050 return true;
39051 }
39052 }
39053 <?php
39054
39055
39056
39057
39058
39059
39060
39061
39062
39063
39064
39065 namespace Composer\Repository\Vcs;
39066
39067 use Composer\Config;
39068 use Composer\Downloader\TransportException;
39069 use Composer\Json\JsonFile;
39070 use Composer\Cache;
39071 use Composer\IO\IOInterface;
39072 use Composer\Util\GitHub;
39073
39074
39075
39076
39077 class GitHubDriver extends VcsDriver
39078 {
39079 protected $cache;
39080 protected $owner;
39081 protected $repository;
39082 protected $tags;
39083 protected $branches;
39084 protected $rootIdentifier;
39085 protected $repoData;
39086 protected $hasIssues;
39087 protected $infoCache = array();
39088 protected $isPrivate = false;
39089 private $isArchived = false;
39090 private $fundingInfo;
39091
39092
39093
39094
39095
39096
39097 protected $gitDriver;
39098
39099
39100
39101
39102 public function initialize()
39103 {
39104 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
39105 $this->owner = $match[3];
39106 $this->repository = $match[4];
39107 $this->originUrl = strtolower(!empty($match[1]) ? $match[1] : $match[2]);
39108 if ($this->originUrl === 'www.github.com') {
39109 $this->originUrl = 'github.com';
39110 }
39111 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
39112
39113 if ( $this->config->get('use-github-api') === false || (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api'] ) ){
39114 $this->setupGitDriver($this->url);
39115
39116 return;
39117 }
39118
39119 $this->fetchRootIdentifier();
39120 }
39121
39122 public function getRepositoryUrl()
39123 {
39124 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
39125 }
39126
39127
39128
39129
39130 public function getRootIdentifier()
39131 {
39132 if ($this->gitDriver) {
39133 return $this->gitDriver->getRootIdentifier();
39134 }
39135
39136 return $this->rootIdentifier;
39137 }
39138
39139
39140
39141
39142 public function getUrl()
39143 {
39144 if ($this->gitDriver) {
39145 return $this->gitDriver->getUrl();
39146 }
39147
39148 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
39149 }
39150
39151
39152
39153
39154 protected function getApiUrl()
39155 {
39156 if ('github.com' === $this->originUrl) {
39157 $apiUrl = 'api.github.com';
39158 } else {
39159 $apiUrl = $this->originUrl . '/api/v3';
39160 }
39161
39162 return 'https://' . $apiUrl;
39163 }
39164
39165
39166
39167
39168 public function getSource($identifier)
39169 {
39170 if ($this->gitDriver) {
39171 return $this->gitDriver->getSource($identifier);
39172 }
39173 if ($this->isPrivate) {
39174
39175
39176 $url = $this->generateSshUrl();
39177 } else {
39178 $url = $this->getUrl();
39179 }
39180
39181 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
39182 }
39183
39184
39185
39186
39187 public function getDist($identifier)
39188 {
39189 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
39190
39191 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
39192 }
39193
39194
39195
39196
39197 public function getComposerInformation($identifier)
39198 {
39199 if ($this->gitDriver) {
39200 return $this->gitDriver->getComposerInformation($identifier);
39201 }
39202
39203 if (!isset($this->infoCache[$identifier])) {
39204 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
39205 $composer = JsonFile::parseJson($res);
39206 } else {
39207 $composer = $this->getBaseComposerInformation($identifier);
39208
39209 if ($this->shouldCache($identifier)) {
39210 $this->cache->write($identifier, json_encode($composer));
39211 }
39212 }
39213
39214 if ($composer) {
39215
39216 if (!isset($composer['support']['source'])) {
39217 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
39218 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
39219 }
39220 if (!isset($composer['support']['issues']) && $this->hasIssues) {
39221 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
39222 }
39223 if (!isset($composer['abandoned']) && $this->isArchived) {
39224 $composer['abandoned'] = true;
39225 }
39226 if (!isset($composer['funding']) && $funding = $this->getFundingInfo()) {
39227 $composer['funding'] = $funding;
39228 }
39229 }
39230
39231 $this->infoCache[$identifier] = $composer;
39232 }
39233
39234 return $this->infoCache[$identifier];
39235 }
39236
39237 private function getFundingInfo()
39238 {
39239 if (null !== $this->fundingInfo) {
39240 return $this->fundingInfo;
39241 }
39242
39243 if ($this->originUrl !== 'github.com') {
39244 return $this->fundingInfo = false;
39245 }
39246
39247 foreach (array($this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/.github/FUNDING.yml', $this->getApiUrl() . '/repos/'.$this->owner.'/.github/contents/FUNDING.yml') as $file) {
39248
39249 try {
39250 $result = $this->remoteFilesystem->getContents($this->originUrl, $file, false, array(
39251 'retry-auth-failure' => false,
39252 ));
39253 $response = json_decode($result, true);
39254 } catch (TransportException $e) {
39255 continue;
39256 }
39257 if (empty($response['content']) || $response['encoding'] !== 'base64' || !($funding = base64_decode($response['content']))) {
39258 continue;
39259 }
39260 break;
39261 }
39262 if (empty($funding)) {
39263 return $this->fundingInfo = false;
39264 }
39265
39266 $result = array();
39267 $key = null;
39268 foreach (preg_split('{\r?\n}', $funding) as $line) {
39269 $line = trim($line);
39270 if (preg_match('{^(\w+)\s*:\s*(.+)$}', $line, $match)) {
39271 if (preg_match('{^\[(.*)\](?:\s*#.*)?$}', $match[2], $match2)) {
39272 foreach (array_map('trim', preg_split('{[\'"]?\s*,\s*[\'"]?}', $match2[1])) as $item) {
39273 $result[] = array('type' => $match[1], 'url' => trim($item, '"\' '));
39274 }
39275 } elseif (preg_match('{^([^#].*?)(\s+#.*)?$}', $match[2], $match2)) {
39276 $result[] = array('type' => $match[1], 'url' => trim($match2[1], '"\' '));
39277 }
39278 $key = null;
39279 } elseif (preg_match('{^(\w+)\s*:\s*#\s*$}', $line, $match)) {
39280 $key = $match[1];
39281 } elseif ($key && preg_match('{^-\s*(.+)(\s+#.*)?$}', $line, $match)) {
39282 $result[] = array('type' => $key, 'url' => trim($match[1], '"\' '));
39283 }
39284 }
39285
39286 foreach ($result as $key => $item) {
39287 switch ($item['type']) {
39288 case 'tidelift':
39289 $result[$key]['url'] = 'https://tidelift.com/funding/github/' . $item['url'];
39290 break;
39291 case 'github':
39292 $result[$key]['url'] = 'https://github.com/' . basename($item['url']);
39293 break;
39294 case 'patreon':
39295 $result[$key]['url'] = 'https://www.patreon.com/' . basename($item['url']);
39296 break;
39297 case 'otechie':
39298 $result[$key]['url'] = 'https://otechie.com/' . basename($item['url']);
39299 break;
39300 case 'open_collective':
39301 $result[$key]['url'] = 'https://opencollective.com/' . basename($item['url']);
39302 break;
39303 case 'liberapay':
39304 $result[$key]['url'] = 'https://liberapay.com/' . basename($item['url']);
39305 break;
39306 case 'ko_fi':
39307 $result[$key]['url'] = 'https://ko-fi.com/' . basename($item['url']);
39308 break;
39309 case 'issuehunt':
39310 $result[$key]['url'] = 'https://issuehunt.io/r/' . $item['url'];
39311 break;
39312 case 'community_bridge':
39313 $result[$key]['url'] = 'https://funding.communitybridge.org/projects/' . basename($item['url']);
39314 break;
39315 }
39316 }
39317
39318 return $this->fundingInfo = $result;
39319 }
39320
39321
39322
39323
39324 public function getFileContent($file, $identifier)
39325 {
39326 if ($this->gitDriver) {
39327 return $this->gitDriver->getFileContent($file, $identifier);
39328 }
39329
39330 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
39331 $resource = JsonFile::parseJson($this->getContents($resource));
39332 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
39333 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
39334 }
39335
39336 return $content;
39337 }
39338
39339
39340
39341
39342 public function getChangeDate($identifier)
39343 {
39344 if ($this->gitDriver) {
39345 return $this->gitDriver->getChangeDate($identifier);
39346 }
39347
39348 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
39349 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
39350
39351 return new \DateTime($commit['commit']['committer']['date']);
39352 }
39353
39354
39355
39356
39357 public function getTags()
39358 {
39359 if ($this->gitDriver) {
39360 return $this->gitDriver->getTags();
39361 }
39362 if (null === $this->tags) {
39363 $this->tags = array();
39364 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
39365
39366 do {
39367 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
39368 foreach ($tagsData as $tag) {
39369 $this->tags[$tag['name']] = $tag['commit']['sha'];
39370 }
39371
39372 $resource = $this->getNextPage();
39373 } while ($resource);
39374 }
39375
39376 return $this->tags;
39377 }
39378
39379
39380
39381
39382 public function getBranches()
39383 {
39384 if ($this->gitDriver) {
39385 return $this->gitDriver->getBranches();
39386 }
39387 if (null === $this->branches) {
39388 $this->branches = array();
39389 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
39390
39391 do {
39392 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
39393 foreach ($branchData as $branch) {
39394 $name = substr($branch['ref'], 11);
39395 if ($name !== 'gh-pages') {
39396 $this->branches[$name] = $branch['object']['sha'];
39397 }
39398 }
39399
39400 $resource = $this->getNextPage();
39401 } while ($resource);
39402 }
39403
39404 return $this->branches;
39405 }
39406
39407
39408
39409
39410 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39411 {
39412 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
39413 return false;
39414 }
39415
39416 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
39417 if (!in_array(strtolower(preg_replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) {
39418 return false;
39419 }
39420
39421 if (!extension_loaded('openssl')) {
39422 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
39423
39424 return false;
39425 }
39426
39427 return true;
39428 }
39429
39430
39431
39432
39433
39434
39435 public function getRepoData()
39436 {
39437 $this->fetchRootIdentifier();
39438
39439 return $this->repoData;
39440 }
39441
39442
39443
39444
39445
39446
39447 protected function generateSshUrl()
39448 {
39449 if (false !== strpos($this->originUrl, ':')) {
39450 return 'ssh://git@' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
39451 }
39452
39453 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
39454 }
39455
39456
39457
39458
39459 protected function getContents($url, $fetchingRepoData = false)
39460 {
39461 try {
39462 return parent::getContents($url);
39463 } catch (TransportException $e) {
39464 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
39465
39466 switch ($e->getCode()) {
39467 case 401:
39468 case 404:
39469
39470 if (!$fetchingRepoData) {
39471 throw $e;
39472 }
39473
39474 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
39475 return parent::getContents($url);
39476 }
39477
39478 if (!$this->io->isInteractive()) {
39479 return $this->attemptCloneFallback();
39480 }
39481
39482 $scopesIssued = array();
39483 $scopesNeeded = array();
39484 if ($headers = $e->getHeaders()) {
39485 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
39486 $scopesIssued = explode(' ', $scopes);
39487 }
39488 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
39489 $scopesNeeded = explode(' ', $scopes);
39490 }
39491 }
39492 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
39493
39494
39495 if (!$headers || !count($scopesNeeded) || count($scopesFailed)) {
39496 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
39497 }
39498
39499 return parent::getContents($url);
39500
39501 case 403:
39502 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
39503 return parent::getContents($url);
39504 }
39505
39506 if (!$this->io->isInteractive() && $fetchingRepoData) {
39507 return $this->attemptCloneFallback();
39508 }
39509
39510 $rateLimited = $gitHubUtil->isRateLimited($e->getHeaders());
39511
39512 if (!$this->io->hasAuthentication($this->originUrl)) {
39513 if (!$this->io->isInteractive()) {
39514 $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>');
39515 throw $e;
39516 }
39517
39518 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
39519
39520 return parent::getContents($url);
39521 }
39522
39523 if ($rateLimited) {
39524 $rateLimit = $gitHubUtil->getRateLimit($e->getHeaders());
39525 $this->io->writeError(sprintf(
39526 '<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>',
39527 $rateLimit['limit'],
39528 $rateLimit['reset']
39529 ));
39530 }
39531
39532 throw $e;
39533
39534 default:
39535 throw $e;
39536 }
39537 }
39538 }
39539
39540
39541
39542
39543
39544
39545 protected function fetchRootIdentifier()
39546 {
39547 if ($this->repoData) {
39548 return;
39549 }
39550
39551 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
39552
39553 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
39554 if (null === $this->repoData && null !== $this->gitDriver) {
39555 return;
39556 }
39557
39558 $this->owner = $this->repoData['owner']['login'];
39559 $this->repository = $this->repoData['name'];
39560
39561 $this->isPrivate = !empty($this->repoData['private']);
39562 if (isset($this->repoData['default_branch'])) {
39563 $this->rootIdentifier = $this->repoData['default_branch'];
39564 } elseif (isset($this->repoData['master_branch'])) {
39565 $this->rootIdentifier = $this->repoData['master_branch'];
39566 } else {
39567 $this->rootIdentifier = 'master';
39568 }
39569 $this->hasIssues = !empty($this->repoData['has_issues']);
39570 $this->isArchived = !empty($this->repoData['archived']);
39571 }
39572
39573 protected function attemptCloneFallback()
39574 {
39575 $this->isPrivate = true;
39576
39577 try {
39578
39579
39580
39581
39582 $this->setupGitDriver($this->generateSshUrl());
39583
39584 return;
39585 } catch (\RuntimeException $e) {
39586 $this->gitDriver = null;
39587
39588 $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>');
39589 throw $e;
39590 }
39591 }
39592
39593 protected function setupGitDriver($url)
39594 {
39595 $this->gitDriver = new GitDriver(
39596 array('url' => $url),
39597 $this->io,
39598 $this->config,
39599 $this->process,
39600 $this->remoteFilesystem
39601 );
39602 $this->gitDriver->initialize();
39603 }
39604
39605 protected function getNextPage()
39606 {
39607 $headers = $this->remoteFilesystem->getLastHeaders();
39608 foreach ($headers as $header) {
39609 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
39610 $links = explode(',', $match[1]);
39611 foreach ($links as $link) {
39612 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
39613 return $match[1];
39614 }
39615 }
39616 }
39617 }
39618 }
39619 }
39620 <?php
39621
39622
39623
39624
39625
39626
39627
39628
39629
39630
39631
39632 namespace Composer\Repository\Vcs;
39633
39634 use Composer\Config;
39635 use Composer\Cache;
39636 use Composer\IO\IOInterface;
39637 use Composer\Json\JsonFile;
39638 use Composer\Downloader\TransportException;
39639 use Composer\Util\RemoteFilesystem;
39640 use Composer\Util\GitLab;
39641
39642
39643
39644
39645
39646
39647
39648 class GitLabDriver extends VcsDriver
39649 {
39650 private $scheme;
39651 private $namespace;
39652 private $repository;
39653
39654
39655
39656
39657 private $project;
39658
39659
39660
39661
39662 private $commits = array();
39663
39664
39665
39666
39667 private $tags;
39668
39669
39670
39671
39672 private $branches;
39673
39674
39675
39676
39677
39678
39679 protected $gitDriver;
39680
39681
39682
39683
39684
39685
39686 private $isPrivate = true;
39687
39688
39689
39690
39691 private $hasNonstandardOrigin = false;
39692
39693 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
39694
39695
39696
39697
39698
39699
39700
39701
39702 public function initialize()
39703 {
39704 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
39705 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
39706 }
39707
39708 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
39709 $configuredDomains = $this->config->get('gitlab-domains');
39710 $urlParts = explode('/', $match['parts']);
39711
39712 $this->scheme = !empty($match['scheme'])
39713 ? $match['scheme']
39714 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
39715 ;
39716 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts, $match['port']);
39717
39718 if (false !== strpos($this->originUrl, ':') || false !== strpos($this->originUrl, '/')) {
39719 $this->hasNonstandardOrigin = true;
39720 }
39721
39722 $this->namespace = implode('/', $urlParts);
39723 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
39724
39725 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
39726
39727 $this->fetchProject();
39728 }
39729
39730
39731
39732
39733
39734
39735
39736 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
39737 {
39738 $this->remoteFilesystem = $remoteFilesystem;
39739 }
39740
39741
39742
39743
39744 public function getComposerInformation($identifier)
39745 {
39746 if ($this->gitDriver) {
39747 return $this->gitDriver->getComposerInformation($identifier);
39748 }
39749
39750 if (!isset($this->infoCache[$identifier])) {
39751 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
39752 $composer = JsonFile::parseJson($res);
39753 } else {
39754 $composer = $this->getBaseComposerInformation($identifier);
39755
39756 if ($this->shouldCache($identifier)) {
39757 $this->cache->write($identifier, json_encode($composer));
39758 }
39759 }
39760
39761 if ($composer) {
39762
39763 if (!isset($composer['support']['issues']) && isset($this->project['_links']['issues'])) {
39764 $composer['support']['issues'] = $this->project['_links']['issues'];
39765 }
39766 if (!isset($composer['abandoned']) && !empty($this->project['archived'])) {
39767 $composer['abandoned'] = true;
39768 }
39769 }
39770
39771 $this->infoCache[$identifier] = $composer;
39772 }
39773
39774 return $this->infoCache[$identifier];
39775 }
39776
39777
39778
39779
39780 public function getFileContent($file, $identifier)
39781 {
39782 if ($this->gitDriver) {
39783 return $this->gitDriver->getFileContent($file, $identifier);
39784 }
39785
39786
39787 if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
39788 $branches = $this->getBranches();
39789 if (isset($branches[$identifier])) {
39790 $identifier = $branches[$identifier];
39791 }
39792 }
39793
39794 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
39795
39796 try {
39797 $content = $this->getContents($resource);
39798 } catch (TransportException $e) {
39799 if ($e->getCode() !== 404) {
39800 throw $e;
39801 }
39802
39803 return null;
39804 }
39805
39806 return $content;
39807 }
39808
39809
39810
39811
39812 public function getChangeDate($identifier)
39813 {
39814 if ($this->gitDriver) {
39815 return $this->gitDriver->getChangeDate($identifier);
39816 }
39817
39818 if (isset($this->commits[$identifier])) {
39819 return new \DateTime($this->commits[$identifier]['committed_date']);
39820 }
39821
39822 return new \DateTime();
39823 }
39824
39825
39826
39827
39828 public function getRepositoryUrl()
39829 {
39830 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
39831 }
39832
39833
39834
39835
39836 public function getUrl()
39837 {
39838 if ($this->gitDriver) {
39839 return $this->gitDriver->getUrl();
39840 }
39841
39842 return $this->project['web_url'];
39843 }
39844
39845
39846
39847
39848 public function getDist($identifier)
39849 {
39850 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
39851
39852 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
39853 }
39854
39855
39856
39857
39858 public function getSource($identifier)
39859 {
39860 if ($this->gitDriver) {
39861 return $this->gitDriver->getSource($identifier);
39862 }
39863
39864 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
39865 }
39866
39867
39868
39869
39870 public function getRootIdentifier()
39871 {
39872 if ($this->gitDriver) {
39873 return $this->gitDriver->getRootIdentifier();
39874 }
39875
39876 return $this->project['default_branch'];
39877 }
39878
39879
39880
39881
39882 public function getBranches()
39883 {
39884 if ($this->gitDriver) {
39885 return $this->gitDriver->getBranches();
39886 }
39887
39888 if (!$this->branches) {
39889 $this->branches = $this->getReferences('branches');
39890 }
39891
39892 return $this->branches;
39893 }
39894
39895
39896
39897
39898 public function getTags()
39899 {
39900 if ($this->gitDriver) {
39901 return $this->gitDriver->getTags();
39902 }
39903
39904 if (!$this->tags) {
39905 $this->tags = $this->getReferences('tags');
39906 }
39907
39908 return $this->tags;
39909 }
39910
39911
39912
39913
39914 public function getApiUrl()
39915 {
39916 return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
39917 }
39918
39919
39920
39921
39922
39923
39924
39925 private function urlEncodeAll($string)
39926 {
39927 $encoded = '';
39928 for ($i = 0; isset($string[$i]); $i++) {
39929 $character = $string[$i];
39930 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
39931 $character = '%' . sprintf('%02X', ord($character));
39932 }
39933 $encoded .= $character;
39934 }
39935
39936 return $encoded;
39937 }
39938
39939
39940
39941
39942
39943
39944 protected function getReferences($type)
39945 {
39946 $perPage = 100;
39947 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
39948
39949 $references = array();
39950 do {
39951 $data = JsonFile::parseJson($this->getContents($resource), $resource);
39952
39953 foreach ($data as $datum) {
39954 $references[$datum['name']] = $datum['commit']['id'];
39955
39956
39957
39958 $this->commits[$datum['commit']['id']] = $datum['commit'];
39959 }
39960
39961 if (count($data) >= $perPage) {
39962 $resource = $this->getNextPage();
39963 } else {
39964 $resource = false;
39965 }
39966 } while ($resource);
39967
39968 return $references;
39969 }
39970
39971 protected function fetchProject()
39972 {
39973
39974 $resource = $this->getApiUrl();
39975 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
39976 if (isset($this->project['visibility'])) {
39977 $this->isPrivate = $this->project['visibility'] !== 'public';
39978 } else {
39979
39980 $this->isPrivate = false;
39981 }
39982 }
39983
39984 protected function attemptCloneFallback()
39985 {
39986 try {
39987 if ($this->isPrivate === false) {
39988 $url = $this->generatePublicUrl();
39989 } else {
39990 $url = $this->generateSshUrl();
39991 }
39992
39993
39994
39995
39996 $this->setupGitDriver($url);
39997
39998 return;
39999 } catch (\RuntimeException $e) {
40000 $this->gitDriver = null;
40001
40002 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
40003 throw $e;
40004 }
40005 }
40006
40007
40008
40009
40010
40011
40012 protected function generateSshUrl()
40013 {
40014 if ($this->hasNonstandardOrigin) {
40015 return 'ssh://git@'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository.'.git';
40016 }
40017
40018 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
40019 }
40020
40021 protected function generatePublicUrl()
40022 {
40023 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
40024 }
40025
40026 protected function setupGitDriver($url)
40027 {
40028 $this->gitDriver = new GitDriver(
40029 array('url' => $url),
40030 $this->io,
40031 $this->config,
40032 $this->process,
40033 $this->remoteFilesystem
40034 );
40035 $this->gitDriver->initialize();
40036 }
40037
40038
40039
40040
40041 protected function getContents($url, $fetchingRepoData = false)
40042 {
40043 try {
40044 $res = parent::getContents($url);
40045
40046 if ($fetchingRepoData) {
40047 $json = JsonFile::parseJson($res, $url);
40048
40049
40050
40051
40052 if (!isset($json['default_branch']) && isset($json['permissions'])) {
40053 $this->isPrivate = $json['visibility'] !== 'public';
40054
40055 $moreThanGuestAccess = false;
40056
40057
40058
40059 foreach ($json['permissions'] as $permission) {
40060 if ($permission && $permission['access_level'] > 10) {
40061 $moreThanGuestAccess = true;
40062 }
40063 }
40064
40065 if (!$moreThanGuestAccess) {
40066 $this->io->writeError('<warning>GitLab token with Guest only access detected</warning>');
40067
40068 return $this->attemptCloneFallback();
40069 }
40070 }
40071
40072
40073 if (!isset($json['default_branch'])) {
40074 if (!empty($json['id'])) {
40075 $this->isPrivate = false;
40076 }
40077
40078 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
40079 }
40080 }
40081
40082 return $res;
40083 } catch (TransportException $e) {
40084 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
40085
40086 switch ($e->getCode()) {
40087 case 401:
40088 case 404:
40089
40090 if (!$fetchingRepoData) {
40091 throw $e;
40092 }
40093
40094 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
40095 return parent::getContents($url);
40096 }
40097
40098 if (!$this->io->isInteractive()) {
40099 return $this->attemptCloneFallback();
40100 }
40101 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
40102 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
40103
40104 return parent::getContents($url);
40105
40106 case 403:
40107 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
40108 return parent::getContents($url);
40109 }
40110
40111 if (!$this->io->isInteractive() && $fetchingRepoData) {
40112 return $this->attemptCloneFallback();
40113 }
40114
40115 throw $e;
40116
40117 default:
40118 throw $e;
40119 }
40120 }
40121 }
40122
40123
40124
40125
40126
40127
40128
40129 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
40130 {
40131 if (!preg_match(self::URL_REGEX, $url, $match)) {
40132 return false;
40133 }
40134
40135 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
40136 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
40137 $urlParts = explode('/', $match['parts']);
40138
40139 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts, $match['port'])) {
40140 return false;
40141 }
40142
40143 if ('https' === $scheme && !extension_loaded('openssl')) {
40144 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
40145
40146 return false;
40147 }
40148
40149 return true;
40150 }
40151
40152 private function getNextPage()
40153 {
40154 $headers = $this->remoteFilesystem->getLastHeaders();
40155 foreach ($headers as $header) {
40156 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
40157 $links = explode(',', $match[1]);
40158 foreach ($links as $link) {
40159 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
40160 return $match[1];
40161 }
40162 }
40163 }
40164 }
40165 }
40166
40167
40168
40169
40170
40171
40172
40173 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts, $portNumber)
40174 {
40175 $guessedDomain = strtolower($guessedDomain);
40176
40177 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array($guessedDomain.':'.$portNumber, $configuredDomains))) {
40178 if ($portNumber) {
40179 return $guessedDomain.':'.$portNumber;
40180 }
40181 return $guessedDomain;
40182 }
40183
40184 if ($portNumber) {
40185 $guessedDomain .= ':'.$portNumber;
40186 }
40187
40188 while (null !== ($part = array_shift($urlParts))) {
40189 $guessedDomain .= '/' . $part;
40190
40191 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array(preg_replace('{:\d+}', '', $guessedDomain), $configuredDomains))) {
40192 return $guessedDomain;
40193 }
40194 }
40195
40196 return false;
40197 }
40198 }
40199 <?php
40200
40201
40202
40203
40204
40205
40206
40207
40208
40209
40210
40211 namespace Composer\Repository\Vcs;
40212
40213 use Composer\Config;
40214 use Composer\IO\IOInterface;
40215
40216
40217
40218
40219 class HgBitbucketDriver extends BitbucketDriver
40220 {
40221
40222
40223
40224 public function getRootIdentifier()
40225 {
40226 if ($this->fallbackDriver) {
40227 return $this->fallbackDriver->getRootIdentifier();
40228 }
40229
40230 if (null === $this->rootIdentifier) {
40231 if (! $this->getRepoData()) {
40232 return $this->fallbackDriver->getRootIdentifier();
40233 }
40234
40235 if ($this->vcsType !== 'hg') {
40236 throw new \RuntimeException(
40237 $this->url.' does not appear to be a mercurial repository, use '.
40238 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
40239 );
40240 }
40241
40242 $mainBranchData = $this->getMainBranchData();
40243 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
40244 }
40245
40246 return $this->rootIdentifier;
40247 }
40248
40249
40250
40251
40252 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
40253 {
40254 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#i', $url)) {
40255 return false;
40256 }
40257
40258 if (!extension_loaded('openssl')) {
40259 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
40260
40261 return false;
40262 }
40263
40264 return true;
40265 }
40266
40267
40268
40269
40270 protected function setupFallbackDriver($url)
40271 {
40272 $this->fallbackDriver = new HgDriver(
40273 array('url' => $url),
40274 $this->io,
40275 $this->config,
40276 $this->process,
40277 $this->remoteFilesystem
40278 );
40279 $this->fallbackDriver->initialize();
40280 }
40281
40282
40283
40284
40285 protected function generateSshUrl()
40286 {
40287 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
40288 }
40289 }
40290 <?php
40291
40292
40293
40294
40295
40296
40297
40298
40299
40300
40301
40302 namespace Composer\Repository\Vcs;
40303
40304 use Composer\Config;
40305 use Composer\Cache;
40306 use Composer\Util\Hg as HgUtils;
40307 use Composer\Util\ProcessExecutor;
40308 use Composer\Util\Filesystem;
40309 use Composer\IO\IOInterface;
40310
40311
40312
40313
40314 class HgDriver extends VcsDriver
40315 {
40316 protected $tags;
40317 protected $branches;
40318 protected $rootIdentifier;
40319 protected $repoDir;
40320 protected $infoCache = array();
40321
40322
40323
40324
40325 public function initialize()
40326 {
40327 if (Filesystem::isLocalPath($this->url)) {
40328 $this->repoDir = $this->url;
40329 } else {
40330 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
40331 throw new \RuntimeException('HgDriver requires a usable cache directory, and it looks like you set it to be disabled');
40332 }
40333
40334 $cacheDir = $this->config->get('cache-vcs-dir');
40335 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
40336
40337 $fs = new Filesystem();
40338 $fs->ensureDirectoryExists($cacheDir);
40339
40340 if (!is_writable(dirname($this->repoDir))) {
40341 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
40342 }
40343
40344
40345 $this->config->prohibitUrlByConfig($this->url, $this->io);
40346
40347 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
40348
40349
40350 if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
40351 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
40352 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
40353 }
40354 } else {
40355
40356 $fs->removeDirectory($this->repoDir);
40357
40358 $repoDir = $this->repoDir;
40359 $command = function ($url) use ($repoDir) {
40360 return sprintf('hg clone --noupdate -- %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
40361 };
40362
40363 $hgUtils->runCommand($command, $this->url, null);
40364 }
40365 }
40366
40367 $this->getTags();
40368 $this->getBranches();
40369 }
40370
40371
40372
40373
40374 public function getRootIdentifier()
40375 {
40376 if (null === $this->rootIdentifier) {
40377 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
40378 $output = $this->process->splitLines($output);
40379 $this->rootIdentifier = $output[0];
40380 }
40381
40382 return $this->rootIdentifier;
40383 }
40384
40385
40386
40387
40388 public function getUrl()
40389 {
40390 return $this->url;
40391 }
40392
40393
40394
40395
40396 public function getSource($identifier)
40397 {
40398 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
40399 }
40400
40401
40402
40403
40404 public function getDist($identifier)
40405 {
40406 return null;
40407 }
40408
40409
40410
40411
40412 public function getFileContent($file, $identifier)
40413 {
40414 if (isset($identifier[0]) && $identifier[0] === '-') {
40415 throw new \RuntimeException('Invalid hg identifier detected. Identifier must not start with a -, given: ' . $identifier);
40416 }
40417
40418 $resource = sprintf('hg cat -r %s -- %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
40419 $this->process->execute($resource, $content, $this->repoDir);
40420
40421 if (!trim($content)) {
40422 return;
40423 }
40424
40425 return $content;
40426 }
40427
40428
40429
40430
40431 public function getChangeDate($identifier)
40432 {
40433 $this->process->execute(
40434 sprintf(
40435 'hg log --template "{date|rfc3339date}" -r %s',
40436 ProcessExecutor::escape($identifier)
40437 ),
40438 $output,
40439 $this->repoDir
40440 );
40441
40442 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
40443 }
40444
40445
40446
40447
40448 public function getTags()
40449 {
40450 if (null === $this->tags) {
40451 $tags = array();
40452
40453 $this->process->execute('hg tags', $output, $this->repoDir);
40454 foreach ($this->process->splitLines($output) as $tag) {
40455 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
40456 $tags[$match[1]] = $match[2];
40457 }
40458 }
40459 unset($tags['tip']);
40460
40461 $this->tags = $tags;
40462 }
40463
40464 return $this->tags;
40465 }
40466
40467
40468
40469
40470 public function getBranches()
40471 {
40472 if (null === $this->branches) {
40473 $branches = array();
40474 $bookmarks = array();
40475
40476 $this->process->execute('hg branches', $output, $this->repoDir);
40477 foreach ($this->process->splitLines($output) as $branch) {
40478 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match) && $match[1][0] !== '-') {
40479 $branches[$match[1]] = $match[2];
40480 }
40481 }
40482
40483 $this->process->execute('hg bookmarks', $output, $this->repoDir);
40484 foreach ($this->process->splitLines($output) as $branch) {
40485 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match) && $match[1][0] !== '-') {
40486 $bookmarks[$match[1]] = $match[2];
40487 }
40488 }
40489
40490
40491 $this->branches = array_merge($bookmarks, $branches);
40492 }
40493
40494 return $this->branches;
40495 }
40496
40497
40498
40499
40500 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
40501 {
40502 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
40503 return true;
40504 }
40505
40506
40507 if (Filesystem::isLocalPath($url)) {
40508 $url = Filesystem::getPlatformPath($url);
40509 if (!is_dir($url)) {
40510 return false;
40511 }
40512
40513 $process = new ProcessExecutor($io);
40514
40515 if ($process->execute('hg summary', $output, $url) === 0) {
40516 return true;
40517 }
40518 }
40519
40520 if (!$deep) {
40521 return false;
40522 }
40523
40524 $processExecutor = new ProcessExecutor($io);
40525 $exit = $processExecutor->execute(sprintf('hg identify -- %s', ProcessExecutor::escape($url)), $ignored);
40526
40527 return $exit === 0;
40528 }
40529 }
40530 <?php
40531
40532
40533
40534
40535
40536
40537
40538
40539
40540
40541
40542 namespace Composer\Repository\Vcs;
40543
40544 use Composer\Config;
40545 use Composer\Cache;
40546 use Composer\IO\IOInterface;
40547 use Composer\Util\ProcessExecutor;
40548 use Composer\Util\Perforce;
40549
40550
40551
40552
40553 class PerforceDriver extends VcsDriver
40554 {
40555 protected $depot;
40556 protected $branch;
40557
40558 protected $perforce;
40559
40560
40561
40562
40563 public function initialize()
40564 {
40565 $this->depot = $this->repoConfig['depot'];
40566 $this->branch = '';
40567 if (!empty($this->repoConfig['branch'])) {
40568 $this->branch = $this->repoConfig['branch'];
40569 }
40570
40571 $this->initPerforce($this->repoConfig);
40572 $this->perforce->p4Login();
40573 $this->perforce->checkStream();
40574
40575 $this->perforce->writeP4ClientSpec();
40576 $this->perforce->connectClient();
40577
40578 return true;
40579 }
40580
40581 private function initPerforce($repoConfig)
40582 {
40583 if (!empty($this->perforce)) {
40584 return;
40585 }
40586
40587 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
40588 throw new \RuntimeException('PerforceDriver requires a usable cache directory, and it looks like you set it to be disabled');
40589 }
40590
40591 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
40592 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
40593 }
40594
40595
40596
40597
40598 public function getFileContent($file, $identifier)
40599 {
40600 return $this->perforce->getFileContent($file, $identifier);
40601 }
40602
40603
40604
40605
40606 public function getChangeDate($identifier)
40607 {
40608 return null;
40609 }
40610
40611
40612
40613
40614 public function getRootIdentifier()
40615 {
40616 return $this->branch;
40617 }
40618
40619
40620
40621
40622 public function getBranches()
40623 {
40624 return $this->perforce->getBranches();
40625 }
40626
40627
40628
40629
40630 public function getTags()
40631 {
40632 return $this->perforce->getTags();
40633 }
40634
40635
40636
40637
40638 public function getDist($identifier)
40639 {
40640 return null;
40641 }
40642
40643
40644
40645
40646 public function getSource($identifier)
40647 {
40648 $source = array(
40649 'type' => 'perforce',
40650 'url' => $this->repoConfig['url'],
40651 'reference' => $identifier,
40652 'p4user' => $this->perforce->getUser(),
40653 );
40654
40655 return $source;
40656 }
40657
40658
40659
40660
40661 public function getUrl()
40662 {
40663 return $this->url;
40664 }
40665
40666
40667
40668
40669 public function hasComposerFile($identifier)
40670 {
40671 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
40672 $composerInfoIdentifier = $identifier;
40673
40674 return !empty($composerInfo);
40675 }
40676
40677
40678
40679
40680 public function getContents($url)
40681 {
40682 return false;
40683 }
40684
40685
40686
40687
40688 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
40689 {
40690 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
40691 return Perforce::checkServerExists($url, new ProcessExecutor($io));
40692 }
40693
40694 return false;
40695 }
40696
40697
40698
40699
40700 public function cleanup()
40701 {
40702 $this->perforce->cleanupClientSpec();
40703 $this->perforce = null;
40704 }
40705
40706 public function getDepot()
40707 {
40708 return $this->depot;
40709 }
40710
40711 public function getBranch()
40712 {
40713 return $this->branch;
40714 }
40715 }
40716 <?php
40717
40718
40719
40720
40721
40722
40723
40724
40725
40726
40727
40728 namespace Composer\Repository\Vcs;
40729
40730 use Composer\Cache;
40731 use Composer\Config;
40732 use Composer\Json\JsonFile;
40733 use Composer\Util\ProcessExecutor;
40734 use Composer\Util\Filesystem;
40735 use Composer\Util\Svn as SvnUtil;
40736 use Composer\IO\IOInterface;
40737 use Composer\Downloader\TransportException;
40738
40739
40740
40741
40742
40743 class SvnDriver extends VcsDriver
40744 {
40745
40746
40747
40748 protected $cache;
40749 protected $baseUrl;
40750 protected $tags;
40751 protected $branches;
40752 protected $rootIdentifier;
40753 protected $infoCache = array();
40754
40755 protected $trunkPath = 'trunk';
40756 protected $branchesPath = 'branches';
40757 protected $tagsPath = 'tags';
40758 protected $packagePath = '';
40759 protected $cacheCredentials = true;
40760
40761
40762
40763
40764 private $util;
40765
40766
40767
40768
40769 public function initialize()
40770 {
40771 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
40772
40773 SvnUtil::cleanEnv();
40774
40775 if (isset($this->repoConfig['trunk-path'])) {
40776 $this->trunkPath = $this->repoConfig['trunk-path'];
40777 }
40778 if (isset($this->repoConfig['branches-path'])) {
40779 $this->branchesPath = $this->repoConfig['branches-path'];
40780 }
40781 if (isset($this->repoConfig['tags-path'])) {
40782 $this->tagsPath = $this->repoConfig['tags-path'];
40783 }
40784 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
40785 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
40786 }
40787 if (isset($this->repoConfig['package-path'])) {
40788 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
40789 }
40790
40791 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
40792 $this->baseUrl = substr($this->url, 0, $pos);
40793 }
40794
40795 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
40796
40797 $this->getBranches();
40798 $this->getTags();
40799 }
40800
40801
40802
40803
40804 public function getRootIdentifier()
40805 {
40806 return $this->rootIdentifier ?: $this->trunkPath;
40807 }
40808
40809
40810
40811
40812 public function getUrl()
40813 {
40814 return $this->url;
40815 }
40816
40817
40818
40819
40820 public function getSource($identifier)
40821 {
40822 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
40823 }
40824
40825
40826
40827
40828 public function getDist($identifier)
40829 {
40830 return null;
40831 }
40832
40833
40834
40835
40836 protected function shouldCache($identifier)
40837 {
40838 return $this->cache && preg_match('{@\d+$}', $identifier);
40839 }
40840
40841
40842
40843
40844 public function getComposerInformation($identifier)
40845 {
40846 if (!isset($this->infoCache[$identifier])) {
40847 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier.'.json')) {
40848 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
40849 }
40850
40851 try {
40852 $composer = $this->getBaseComposerInformation($identifier);
40853 } catch (TransportException $e) {
40854 $message = $e->getMessage();
40855 if (stripos($message, 'path not found') === false && stripos($message, 'svn: warning: W160013') === false) {
40856 throw $e;
40857 }
40858
40859 $composer = '';
40860 }
40861
40862 if ($this->shouldCache($identifier)) {
40863 $this->cache->write($identifier.'.json', json_encode($composer));
40864 }
40865
40866 $this->infoCache[$identifier] = $composer;
40867 }
40868
40869 return $this->infoCache[$identifier];
40870 }
40871
40872
40873
40874
40875
40876 public function getFileContent($file, $identifier)
40877 {
40878 $identifier = '/' . trim($identifier, '/') . '/';
40879
40880 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
40881 if (!empty($match[2])) {
40882 $path = $match[1];
40883 $rev = $match[2];
40884 } else {
40885 $path = $identifier;
40886 $rev = '';
40887 }
40888
40889 try {
40890 $resource = $path.$file;
40891 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
40892 if (!trim($output)) {
40893 return null;
40894 }
40895 } catch (\RuntimeException $e) {
40896 throw new TransportException($e->getMessage());
40897 }
40898
40899 return $output;
40900 }
40901
40902
40903
40904
40905 public function getChangeDate($identifier)
40906 {
40907 $identifier = '/' . trim($identifier, '/') . '/';
40908
40909 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
40910 if (!empty($match[2])) {
40911 $path = $match[1];
40912 $rev = $match[2];
40913 } else {
40914 $path = $identifier;
40915 $rev = '';
40916 }
40917
40918 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
40919 foreach ($this->process->splitLines($output) as $line) {
40920 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
40921 return new \DateTime($match[1], new \DateTimeZone('UTC'));
40922 }
40923 }
40924
40925 return null;
40926 }
40927
40928
40929
40930
40931 public function getTags()
40932 {
40933 if (null === $this->tags) {
40934 $this->tags = array();
40935
40936 if ($this->tagsPath !== false) {
40937 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
40938 if ($output) {
40939 foreach ($this->process->splitLines($output) as $line) {
40940 $line = trim($line);
40941 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
40942 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
40943 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
40944 '/' . $this->tagsPath . '/' . $match[2],
40945 $match[1]
40946 );
40947 }
40948 }
40949 }
40950 }
40951 }
40952 }
40953
40954 return $this->tags;
40955 }
40956
40957
40958
40959
40960 public function getBranches()
40961 {
40962 if (null === $this->branches) {
40963 $this->branches = array();
40964
40965 if (false === $this->trunkPath) {
40966 $trunkParent = $this->baseUrl . '/';
40967 } else {
40968 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
40969 }
40970
40971 $output = $this->execute('svn ls --verbose', $trunkParent);
40972 if ($output) {
40973 foreach ($this->process->splitLines($output) as $line) {
40974 $line = trim($line);
40975 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
40976 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
40977 $this->branches['trunk'] = $this->buildIdentifier(
40978 '/' . $this->trunkPath,
40979 $match[1]
40980 );
40981 $this->rootIdentifier = $this->branches['trunk'];
40982 break;
40983 }
40984 }
40985 }
40986 }
40987 unset($output);
40988
40989 if ($this->branchesPath !== false) {
40990 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
40991 if ($output) {
40992 foreach ($this->process->splitLines(trim($output)) as $line) {
40993 $line = trim($line);
40994 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
40995 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
40996 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
40997 '/' . $this->branchesPath . '/' . $match[2],
40998 $match[1]
40999 );
41000 }
41001 }
41002 }
41003 }
41004 }
41005 }
41006
41007 return $this->branches;
41008 }
41009
41010
41011
41012
41013 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
41014 {
41015 $url = self::normalizeUrl($url);
41016 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
41017 return true;
41018 }
41019
41020
41021 if (!$deep && !Filesystem::isLocalPath($url)) {
41022 return false;
41023 }
41024
41025 $processExecutor = new ProcessExecutor($io);
41026
41027 $exit = $processExecutor->execute(
41028 "svn info --non-interactive -- ".ProcessExecutor::escape($url),
41029 $ignoredOutput
41030 );
41031
41032 if ($exit === 0) {
41033
41034 return true;
41035 }
41036
41037
41038 if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
41039
41040
41041 return true;
41042 }
41043
41044
41045 if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
41046
41047
41048 return true;
41049 }
41050
41051 return false;
41052 }
41053
41054
41055
41056
41057
41058
41059
41060
41061 protected static function normalizeUrl($url)
41062 {
41063 $fs = new Filesystem();
41064 if ($fs->isAbsolutePath($url)) {
41065 return 'file://' . strtr($url, '\\', '/');
41066 }
41067
41068 return $url;
41069 }
41070
41071
41072
41073
41074
41075
41076
41077
41078
41079
41080 protected function execute($command, $url)
41081 {
41082 if (null === $this->util) {
41083 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
41084 $this->util->setCacheCredentials($this->cacheCredentials);
41085 }
41086
41087 try {
41088 return $this->util->execute($command, $url);
41089 } catch (\RuntimeException $e) {
41090 if (null === $this->util->binaryVersion()) {
41091 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());
41092 }
41093
41094 throw new \RuntimeException(
41095 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
41096 );
41097 }
41098 }
41099
41100
41101
41102
41103
41104
41105
41106
41107
41108 protected function buildIdentifier($baseDir, $revision)
41109 {
41110 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
41111 }
41112 }
41113 <?php
41114
41115
41116
41117
41118
41119
41120
41121
41122
41123
41124
41125 namespace Composer\Repository\Vcs;
41126
41127 use Composer\Cache;
41128 use Composer\Downloader\TransportException;
41129 use Composer\Config;
41130 use Composer\Factory;
41131 use Composer\IO\IOInterface;
41132 use Composer\Json\JsonFile;
41133 use Composer\Util\ProcessExecutor;
41134 use Composer\Util\RemoteFilesystem;
41135 use Composer\Util\Filesystem;
41136
41137
41138
41139
41140
41141
41142 abstract class VcsDriver implements VcsDriverInterface
41143 {
41144
41145 protected $url;
41146
41147 protected $originUrl;
41148
41149 protected $repoConfig;
41150
41151 protected $io;
41152
41153 protected $config;
41154
41155 protected $process;
41156
41157 protected $remoteFilesystem;
41158
41159 protected $infoCache = array();
41160
41161 protected $cache;
41162
41163
41164
41165
41166
41167
41168
41169
41170
41171
41172 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
41173 {
41174 if (Filesystem::isLocalPath($repoConfig['url'])) {
41175 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
41176 }
41177
41178 $this->url = $repoConfig['url'];
41179 $this->originUrl = $repoConfig['url'];
41180 $this->repoConfig = $repoConfig;
41181 $this->io = $io;
41182 $this->config = $config;
41183 $this->process = $process ?: new ProcessExecutor($io);
41184 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41185 }
41186
41187
41188
41189
41190
41191
41192
41193 protected function shouldCache($identifier)
41194 {
41195 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
41196 }
41197
41198
41199
41200
41201 public function getComposerInformation($identifier)
41202 {
41203 if (!isset($this->infoCache[$identifier])) {
41204 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
41205 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
41206 }
41207
41208 $composer = $this->getBaseComposerInformation($identifier);
41209
41210 if ($this->shouldCache($identifier)) {
41211 $this->cache->write($identifier, json_encode($composer));
41212 }
41213
41214 $this->infoCache[$identifier] = $composer;
41215 }
41216
41217 return $this->infoCache[$identifier];
41218 }
41219
41220 protected function getBaseComposerInformation($identifier)
41221 {
41222 $composerFileContent = $this->getFileContent('composer.json', $identifier);
41223
41224 if (!$composerFileContent) {
41225 return null;
41226 }
41227
41228 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
41229
41230 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
41231 $composer['time'] = $changeDate->format(DATE_RFC3339);
41232 }
41233
41234 return $composer;
41235 }
41236
41237
41238
41239
41240 public function hasComposerFile($identifier)
41241 {
41242 try {
41243 return (bool) $this->getComposerInformation($identifier);
41244 } catch (TransportException $e) {
41245 }
41246
41247 return false;
41248 }
41249
41250
41251
41252
41253
41254
41255
41256
41257 protected function getScheme()
41258 {
41259 if (extension_loaded('openssl')) {
41260 return 'https';
41261 }
41262
41263 return 'http';
41264 }
41265
41266
41267
41268
41269
41270
41271
41272
41273 protected function getContents($url)
41274 {
41275 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
41276
41277 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
41278 }
41279
41280
41281
41282
41283 public function cleanup()
41284 {
41285 return;
41286 }
41287 }
41288 <?php
41289
41290
41291
41292
41293
41294
41295
41296
41297
41298
41299
41300 namespace Composer\Repository\Vcs;
41301
41302 use Composer\Config;
41303 use Composer\IO\IOInterface;
41304
41305
41306
41307
41308 interface VcsDriverInterface
41309 {
41310
41311
41312
41313 public function initialize();
41314
41315
41316
41317
41318
41319
41320
41321 public function getComposerInformation($identifier);
41322
41323
41324
41325
41326
41327
41328
41329
41330 public function getFileContent($file, $identifier);
41331
41332
41333
41334
41335
41336
41337
41338 public function getChangeDate($identifier);
41339
41340
41341
41342
41343
41344
41345 public function getRootIdentifier();
41346
41347
41348
41349
41350
41351
41352 public function getBranches();
41353
41354
41355
41356
41357
41358
41359 public function getTags();
41360
41361
41362
41363
41364
41365 public function getDist($identifier);
41366
41367
41368
41369
41370
41371 public function getSource($identifier);
41372
41373
41374
41375
41376
41377
41378 public function getUrl();
41379
41380
41381
41382
41383
41384
41385
41386
41387 public function hasComposerFile($identifier);
41388
41389
41390
41391
41392 public function cleanup();
41393
41394
41395
41396
41397
41398
41399
41400
41401
41402
41403 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
41404 }
41405 <?php
41406
41407
41408
41409
41410
41411
41412
41413
41414
41415
41416
41417 namespace Composer\Repository;
41418
41419 use Composer\Downloader\TransportException;
41420 use Composer\Repository\Vcs\VcsDriverInterface;
41421 use Composer\Package\Version\VersionParser;
41422 use Composer\Package\Loader\ArrayLoader;
41423 use Composer\Package\Loader\ValidatingArrayLoader;
41424 use Composer\Package\Loader\InvalidPackageException;
41425 use Composer\Package\Loader\LoaderInterface;
41426 use Composer\EventDispatcher\EventDispatcher;
41427 use Composer\Semver\Constraint\Constraint;
41428 use Composer\IO\IOInterface;
41429 use Composer\Config;
41430
41431
41432
41433
41434 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
41435 {
41436 protected $url;
41437 protected $packageName;
41438 protected $isVerbose;
41439 protected $isVeryVerbose;
41440 protected $io;
41441 protected $config;
41442 protected $versionParser;
41443 protected $type;
41444 protected $loader;
41445 protected $repoConfig;
41446 protected $branchErrorOccurred = false;
41447 private $drivers;
41448
41449 private $driver;
41450
41451 private $versionCache;
41452 private $emptyReferences = array();
41453 private $versionTransportExceptions = array();
41454
41455 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null, VersionCacheInterface $versionCache = null)
41456 {
41457 parent::__construct();
41458 $this->drivers = $drivers ?: array(
41459 'github' => 'Composer\Repository\Vcs\GitHubDriver',
41460 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
41461 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
41462 'git' => 'Composer\Repository\Vcs\GitDriver',
41463 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
41464 'hg' => 'Composer\Repository\Vcs\HgDriver',
41465 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
41466 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
41467
41468 'svn' => 'Composer\Repository\Vcs\SvnDriver',
41469 );
41470
41471 $this->url = $repoConfig['url'];
41472 $this->io = $io;
41473 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
41474 $this->isVerbose = $io->isVerbose();
41475 $this->isVeryVerbose = $io->isVeryVerbose();
41476 $this->config = $config;
41477 $this->repoConfig = $repoConfig;
41478 $this->versionCache = $versionCache;
41479 }
41480
41481 public function getRepoConfig()
41482 {
41483 return $this->repoConfig;
41484 }
41485
41486 public function setLoader(LoaderInterface $loader)
41487 {
41488 $this->loader = $loader;
41489 }
41490
41491 public function getDriver()
41492 {
41493 if ($this->driver) {
41494 return $this->driver;
41495 }
41496
41497 if (isset($this->drivers[$this->type])) {
41498 $class = $this->drivers[$this->type];
41499 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
41500 $this->driver->initialize();
41501
41502 return $this->driver;
41503 }
41504
41505 foreach ($this->drivers as $driver) {
41506 if ($driver::supports($this->io, $this->config, $this->url)) {
41507 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
41508 $this->driver->initialize();
41509
41510 return $this->driver;
41511 }
41512 }
41513
41514 foreach ($this->drivers as $driver) {
41515 if ($driver::supports($this->io, $this->config, $this->url, true)) {
41516 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
41517 $this->driver->initialize();
41518
41519 return $this->driver;
41520 }
41521 }
41522 }
41523
41524 public function hadInvalidBranches()
41525 {
41526 return $this->branchErrorOccurred;
41527 }
41528
41529 public function getEmptyReferences()
41530 {
41531 return $this->emptyReferences;
41532 }
41533
41534 public function getVersionTransportExceptions()
41535 {
41536 return $this->versionTransportExceptions;
41537 }
41538
41539 protected function initialize()
41540 {
41541 parent::initialize();
41542
41543 $isVerbose = $this->isVerbose;
41544 $isVeryVerbose = $this->isVeryVerbose;
41545
41546 $driver = $this->getDriver();
41547 if (!$driver) {
41548 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
41549 }
41550
41551 $this->versionParser = new VersionParser;
41552 if (!$this->loader) {
41553 $this->loader = new ArrayLoader($this->versionParser);
41554 }
41555
41556 try {
41557 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
41558 $data = $driver->getComposerInformation($driver->getRootIdentifier());
41559 $this->packageName = !empty($data['name']) ? $data['name'] : null;
41560 }
41561 } catch (\Exception $e) {
41562 if ($isVeryVerbose) {
41563 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
41564 }
41565 }
41566
41567 foreach ($driver->getTags() as $tag => $identifier) {
41568 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
41569 if ($isVeryVerbose) {
41570 $this->io->writeError($msg);
41571 } elseif ($isVerbose) {
41572 $this->io->overwriteError($msg, false);
41573 }
41574
41575
41576 $tag = str_replace('release-', '', $tag);
41577
41578 $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose);
41579 if ($cachedPackage) {
41580 $this->addPackage($cachedPackage);
41581
41582 continue;
41583 } elseif ($cachedPackage === false) {
41584 $this->emptyReferences[] = $identifier;
41585
41586 continue;
41587 }
41588
41589 if (!$parsedTag = $this->validateTag($tag)) {
41590 if ($isVeryVerbose) {
41591 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
41592 }
41593 continue;
41594 }
41595
41596 try {
41597 if (!$data = $driver->getComposerInformation($identifier)) {
41598 if ($isVeryVerbose) {
41599 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
41600 }
41601 $this->emptyReferences[] = $identifier;
41602 continue;
41603 }
41604
41605
41606 if (isset($data['version'])) {
41607 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
41608 } else {
41609
41610 $data['version'] = $tag;
41611 $data['version_normalized'] = $parsedTag;
41612 }
41613
41614
41615 $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
41616 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
41617
41618
41619 if ($data['version_normalized'] !== $parsedTag) {
41620 if ($isVeryVerbose) {
41621 if (preg_match('{(^dev-|[.-]?dev$)}i', $parsedTag)) {
41622 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name, tags can not use dev prefixes or suffixes</warning>');
41623 } else {
41624 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
41625 }
41626 }
41627 continue;
41628 }
41629
41630 $tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
41631 if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
41632 if ($isVeryVerbose) {
41633 $this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
41634 }
41635 continue;
41636 }
41637
41638 if ($isVeryVerbose) {
41639 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
41640 }
41641
41642 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
41643 } catch (\Exception $e) {
41644 if ($e instanceof TransportException) {
41645 $this->versionTransportExceptions['tags'][$tag] = $e;
41646 if ($e->getCode() === 404) {
41647 $this->emptyReferences[] = $identifier;
41648 }
41649 }
41650 if ($isVeryVerbose) {
41651 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found (' . $e->getCode() . ' HTTP status code)' : $e->getMessage()).'</warning>');
41652 }
41653 continue;
41654 }
41655 }
41656
41657 if (!$isVeryVerbose) {
41658 $this->io->overwriteError('', false);
41659 }
41660
41661 $branches = $driver->getBranches();
41662 foreach ($branches as $branch => $identifier) {
41663 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
41664 if ($isVeryVerbose) {
41665 $this->io->writeError($msg);
41666 } elseif ($isVerbose) {
41667 $this->io->overwriteError($msg, false);
41668 }
41669
41670 if ($branch === 'trunk' && isset($branches['master'])) {
41671 if ($isVeryVerbose) {
41672 $this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
41673 }
41674 continue;
41675 }
41676
41677 if (!$parsedBranch = $this->validateBranch($branch)) {
41678 if ($isVeryVerbose) {
41679 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
41680 }
41681 continue;
41682 }
41683
41684
41685 if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
41686 $version = 'dev-' . $branch;
41687 } else {
41688 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
41689 $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
41690 }
41691
41692 $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose);
41693 if ($cachedPackage) {
41694 $this->addPackage($cachedPackage);
41695
41696 continue;
41697 } elseif ($cachedPackage === false) {
41698 $this->emptyReferences[] = $identifier;
41699
41700 continue;
41701 }
41702
41703 try {
41704 if (!$data = $driver->getComposerInformation($identifier)) {
41705 if ($isVeryVerbose) {
41706 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
41707 }
41708 $this->emptyReferences[] = $identifier;
41709 continue;
41710 }
41711
41712
41713 $data['version'] = $version;
41714 $data['version_normalized'] = $parsedBranch;
41715
41716 if ($isVeryVerbose) {
41717 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
41718 }
41719
41720 $packageData = $this->preProcess($driver, $data, $identifier);
41721 $package = $this->loader->load($packageData);
41722 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
41723 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
41724 }
41725 $this->addPackage($package);
41726 } catch (TransportException $e) {
41727 $this->versionTransportExceptions['branches'][$branch] = $e;
41728 if ($e->getCode() === 404) {
41729 $this->emptyReferences[] = $identifier;
41730 }
41731 if ($isVeryVerbose) {
41732 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found (' . $e->getCode() . ' HTTP status code)</warning>');
41733 }
41734 continue;
41735 } catch (\Exception $e) {
41736 if (!$isVeryVerbose) {
41737 $this->io->writeError('');
41738 }
41739 $this->branchErrorOccurred = true;
41740 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
41741 $this->io->writeError('');
41742 continue;
41743 }
41744 }
41745 $driver->cleanup();
41746
41747 if (!$isVeryVerbose) {
41748 $this->io->overwriteError('', false);
41749 }
41750
41751 if (!$this->getPackages()) {
41752 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
41753 }
41754 }
41755
41756 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
41757 {
41758
41759 $dataPackageName = isset($data['name']) ? $data['name'] : null;
41760 $data['name'] = $this->packageName ?: $dataPackageName;
41761
41762 if (!isset($data['dist'])) {
41763 $data['dist'] = $driver->getDist($identifier);
41764 }
41765 if (!isset($data['source'])) {
41766 $data['source'] = $driver->getSource($identifier);
41767 }
41768
41769 return $data;
41770 }
41771
41772 private function validateBranch($branch)
41773 {
41774 try {
41775 $normalizedBranch = $this->versionParser->normalizeBranch($branch);
41776
41777
41778 $this->versionParser->parseConstraints($normalizedBranch);
41779
41780 return $normalizedBranch;
41781 } catch (\Exception $e) {
41782 }
41783
41784 return false;
41785 }
41786
41787 private function validateTag($version)
41788 {
41789 try {
41790 return $this->versionParser->normalize($version);
41791 } catch (\Exception $e) {
41792 }
41793
41794 return false;
41795 }
41796
41797 private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose)
41798 {
41799 if (!$this->versionCache) {
41800 return;
41801 }
41802
41803 $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
41804 if ($cachedPackage === false) {
41805 if ($isVeryVerbose) {
41806 $this->io->writeError('<warning>Skipped '.$version.', no composer file (cached from ref '.$identifier.')</warning>');
41807 }
41808
41809 return false;
41810 }
41811
41812 if ($cachedPackage) {
41813 $msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
41814 if ($isVeryVerbose) {
41815 $this->io->writeError($msg);
41816 } elseif ($isVerbose) {
41817 $this->io->overwriteError($msg, false);
41818 }
41819
41820 if ($existingPackage = $this->findPackage($cachedPackage['name'], new Constraint('=', $cachedPackage['version_normalized']))) {
41821 if ($isVeryVerbose) {
41822 $this->io->writeError('<warning>Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally</warning>');
41823 }
41824 $cachedPackage = null;
41825 }
41826 }
41827
41828 if ($cachedPackage) {
41829 return $this->loader->load($cachedPackage);
41830 }
41831
41832 return null;
41833 }
41834 }
41835 <?php
41836
41837
41838
41839
41840
41841
41842
41843
41844
41845
41846
41847 namespace Composer\Repository;
41848
41849 interface VersionCacheInterface
41850 {
41851
41852
41853
41854
41855
41856 public function getVersionPackage($version, $identifier);
41857 }
41858 <?php
41859
41860
41861
41862
41863
41864
41865
41866
41867
41868
41869
41870 namespace Composer\Repository;
41871
41872 use Composer\Package\AliasPackage;
41873
41874
41875
41876
41877
41878
41879 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
41880 {
41881
41882
41883
41884 public function write()
41885 {
41886 }
41887
41888
41889
41890
41891 public function reload()
41892 {
41893 }
41894
41895
41896
41897
41898 public function getCanonicalPackages()
41899 {
41900 $packages = $this->getPackages();
41901
41902
41903 $packagesByName = array();
41904 foreach ($packages as $package) {
41905 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
41906 $packagesByName[$package->getName()] = $package;
41907 }
41908 }
41909
41910 $canonicalPackages = array();
41911
41912
41913 foreach ($packagesByName as $package) {
41914 while ($package instanceof AliasPackage) {
41915 $package = $package->getAliasOf();
41916 }
41917
41918 $canonicalPackages[] = $package;
41919 }
41920
41921 return $canonicalPackages;
41922 }
41923 }
41924 <?php
41925
41926
41927
41928
41929
41930
41931
41932
41933
41934
41935
41936 namespace Composer\Repository;
41937
41938 use Composer\Package\PackageInterface;
41939
41940
41941
41942
41943
41944
41945 interface WritableRepositoryInterface extends RepositoryInterface
41946 {
41947
41948
41949
41950 public function write();
41951
41952
41953
41954
41955
41956
41957 public function addPackage(PackageInterface $package);
41958
41959
41960
41961
41962
41963
41964 public function removePackage(PackageInterface $package);
41965
41966
41967
41968
41969
41970
41971 public function getCanonicalPackages();
41972
41973
41974
41975
41976 public function reload();
41977 }
41978 <?php
41979
41980
41981
41982
41983
41984
41985
41986
41987
41988
41989
41990 namespace Composer\Script;
41991
41992
41993
41994
41995
41996
41997 class CommandEvent extends Event
41998 {
41999 }
42000 <?php
42001
42002
42003
42004
42005
42006
42007
42008
42009
42010
42011
42012 namespace Composer\Script;
42013
42014 use Composer\Composer;
42015 use Composer\IO\IOInterface;
42016 use Composer\EventDispatcher\Event as BaseEvent;
42017
42018
42019
42020
42021
42022
42023
42024 class Event extends BaseEvent
42025 {
42026
42027
42028
42029 private $composer;
42030
42031
42032
42033
42034 private $io;
42035
42036
42037
42038
42039 private $devMode;
42040
42041
42042
42043
42044 private $originatingEvent;
42045
42046
42047
42048
42049
42050
42051
42052
42053
42054
42055
42056 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
42057 {
42058 parent::__construct($name, $args, $flags);
42059 $this->composer = $composer;
42060 $this->io = $io;
42061 $this->devMode = $devMode;
42062 $this->originatingEvent = null;
42063 }
42064
42065
42066
42067
42068
42069
42070 public function getComposer()
42071 {
42072 return $this->composer;
42073 }
42074
42075
42076
42077
42078
42079
42080 public function getIO()
42081 {
42082 return $this->io;
42083 }
42084
42085
42086
42087
42088
42089
42090 public function isDevMode()
42091 {
42092 return $this->devMode;
42093 }
42094
42095
42096
42097
42098
42099
42100 public function getOriginatingEvent()
42101 {
42102 return $this->originatingEvent;
42103 }
42104
42105
42106
42107
42108
42109
42110
42111 public function setOriginatingEvent(BaseEvent $event)
42112 {
42113 $this->originatingEvent = $this->calculateOriginatingEvent($event);
42114
42115 return $this;
42116 }
42117
42118
42119
42120
42121
42122
42123
42124 private function calculateOriginatingEvent(BaseEvent $event)
42125 {
42126 if ($event instanceof Event && $event->getOriginatingEvent()) {
42127 return $this->calculateOriginatingEvent($event->getOriginatingEvent());
42128 }
42129
42130 return $event;
42131 }
42132 }
42133 <?php
42134
42135
42136
42137
42138
42139
42140
42141
42142
42143
42144
42145 namespace Composer\Script;
42146
42147 use Composer\Installer\PackageEvent as BasePackageEvent;
42148
42149
42150
42151
42152
42153
42154 class PackageEvent extends BasePackageEvent
42155 {
42156 }
42157 <?php
42158
42159
42160
42161
42162
42163
42164
42165
42166
42167
42168
42169 namespace Composer\Script;
42170
42171
42172
42173
42174
42175
42176
42177 class ScriptEvents
42178 {
42179
42180
42181
42182
42183
42184
42185
42186 const PRE_INSTALL_CMD = 'pre-install-cmd';
42187
42188
42189
42190
42191
42192
42193
42194
42195 const POST_INSTALL_CMD = 'post-install-cmd';
42196
42197
42198
42199
42200
42201
42202
42203
42204 const PRE_UPDATE_CMD = 'pre-update-cmd';
42205
42206
42207
42208
42209
42210
42211
42212
42213 const POST_UPDATE_CMD = 'post-update-cmd';
42214
42215
42216
42217
42218
42219
42220
42221
42222 const PRE_STATUS_CMD = 'pre-status-cmd';
42223
42224
42225
42226
42227
42228
42229
42230
42231 const POST_STATUS_CMD = 'post-status-cmd';
42232
42233
42234
42235
42236
42237
42238
42239
42240 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
42241
42242
42243
42244
42245
42246
42247
42248
42249 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
42250
42251
42252
42253
42254
42255
42256
42257
42258 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
42259
42260
42261
42262
42263
42264
42265
42266
42267
42268 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
42269
42270
42271
42272
42273
42274
42275
42276
42277 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
42278
42279
42280
42281
42282
42283
42284
42285
42286 const POST_ARCHIVE_CMD = 'post-archive-cmd';
42287
42288
42289
42290
42291
42292
42293
42294
42295
42296
42297
42298 const PRE_PACKAGE_INSTALL = 'pre-package-install';
42299
42300
42301
42302
42303
42304
42305
42306
42307
42308 const POST_PACKAGE_INSTALL = 'post-package-install';
42309
42310
42311
42312
42313
42314
42315
42316
42317
42318 const PRE_PACKAGE_UPDATE = 'pre-package-update';
42319
42320
42321
42322
42323
42324
42325
42326
42327
42328 const POST_PACKAGE_UPDATE = 'post-package-update';
42329
42330
42331
42332
42333
42334
42335
42336
42337
42338 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
42339
42340
42341
42342
42343
42344
42345
42346
42347
42348 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
42349 }
42350 <?php
42351
42352
42353
42354
42355
42356
42357
42358
42359
42360
42361
42362 namespace Composer\SelfUpdate;
42363
42364
42365
42366
42367 class Keys
42368 {
42369 public static function fingerprint($path)
42370 {
42371 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
42372
42373 return implode(' ', array(
42374 substr($hash, 0, 8),
42375 substr($hash, 8, 8),
42376 substr($hash, 16, 8),
42377 substr($hash, 24, 8),
42378 '', 
42379 substr($hash, 32, 8),
42380 substr($hash, 40, 8),
42381 substr($hash, 48, 8),
42382 substr($hash, 56, 8),
42383 ));
42384 }
42385 }
42386 <?php
42387
42388
42389
42390
42391
42392
42393
42394
42395
42396
42397
42398 namespace Composer\SelfUpdate;
42399
42400 use Composer\Util\RemoteFilesystem;
42401 use Composer\Config;
42402 use Composer\Json\JsonFile;
42403
42404
42405
42406
42407 class Versions
42408 {
42409 public static $channels = array('stable', 'preview', 'snapshot', '1', '2');
42410
42411 private $rfs;
42412 private $config;
42413 private $channel;
42414 private $versionsData;
42415
42416 public function __construct(Config $config, RemoteFilesystem $rfs)
42417 {
42418 $this->rfs = $rfs;
42419 $this->config = $config;
42420 }
42421
42422 public function getChannel()
42423 {
42424 if ($this->channel) {
42425 return $this->channel;
42426 }
42427
42428 $channelFile = $this->config->get('home').'/update-channel';
42429 if (file_exists($channelFile)) {
42430 $channel = trim(file_get_contents($channelFile));
42431 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
42432 return $this->channel = $channel;
42433 }
42434 }
42435
42436 return $this->channel = 'stable';
42437 }
42438
42439 public function setChannel($channel)
42440 {
42441 if (!in_array($channel, self::$channels, true)) {
42442 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: ' . implode(', ', self::$channels));
42443 }
42444
42445 $channelFile = $this->config->get('home').'/update-channel';
42446 $this->channel = $channel;
42447 file_put_contents($channelFile, (is_numeric($channel) ? 'stable' : $channel).PHP_EOL);
42448 }
42449
42450 public function getLatest($channel = null)
42451 {
42452 $versions = $this->getVersionsData();
42453
42454 foreach ($versions[$channel ?: $this->getChannel()] as $version) {
42455 if ($version['min-php'] <= PHP_VERSION_ID) {
42456 return $version;
42457 }
42458 }
42459
42460 throw new \UnexpectedValueException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
42461 }
42462
42463 private function getVersionsData()
42464 {
42465 if (!$this->versionsData) {
42466 if ($this->config->get('disable-tls') === true) {
42467 $protocol = 'http';
42468 } else {
42469 $protocol = 'https';
42470 }
42471
42472 $this->versionsData = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
42473 }
42474
42475 return $this->versionsData;
42476 }
42477 }
42478 <?php
42479
42480
42481
42482
42483
42484
42485
42486
42487
42488
42489
42490 namespace Composer\Util;
42491
42492 use Composer\Config;
42493 use Composer\IO\IOInterface;
42494
42495
42496
42497
42498 class AuthHelper
42499 {
42500 protected $io;
42501 protected $config;
42502
42503 public function __construct(IOInterface $io, Config $config)
42504 {
42505 $this->io = $io;
42506 $this->config = $config;
42507 }
42508
42509 public function storeAuth($originUrl, $storeAuth)
42510 {
42511 $store = false;
42512 $configSource = $this->config->getAuthConfigSource();
42513 if ($storeAuth === true) {
42514 $store = $configSource;
42515 } elseif ($storeAuth === 'prompt') {
42516 $answer = $this->io->askAndValidate(
42517 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
42518 function ($value) {
42519 $input = strtolower(substr(trim($value), 0, 1));
42520 if (in_array($input, array('y','n'))) {
42521 return $input;
42522 }
42523 throw new \RuntimeException('Please answer (y)es or (n)o');
42524 },
42525 null,
42526 'y'
42527 );
42528
42529 if ($answer === 'y') {
42530 $store = $configSource;
42531 }
42532 }
42533 if ($store) {
42534 $store->addConfigSetting(
42535 'http-basic.'.$originUrl,
42536 $this->io->getAuthentication($originUrl)
42537 );
42538 }
42539 }
42540 }
42541 <?php
42542
42543
42544
42545
42546
42547
42548
42549
42550
42551
42552
42553 namespace Composer\Util;
42554
42555 use Composer\Factory;
42556 use Composer\IO\IOInterface;
42557 use Composer\Config;
42558 use Composer\Downloader\TransportException;
42559
42560
42561
42562
42563 class Bitbucket
42564 {
42565 private $io;
42566 private $config;
42567 private $process;
42568 private $remoteFilesystem;
42569 private $token = array();
42570 private $time;
42571
42572 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
42573
42574
42575
42576
42577
42578
42579
42580
42581
42582
42583 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
42584 {
42585 $this->io = $io;
42586 $this->config = $config;
42587 $this->process = $process ?: new ProcessExecutor($io);
42588 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
42589 $this->time = $time;
42590 }
42591
42592
42593
42594
42595 public function getToken()
42596 {
42597 if (!isset($this->token['access_token'])) {
42598 return '';
42599 }
42600
42601 return $this->token['access_token'];
42602 }
42603
42604
42605
42606
42607
42608
42609
42610 public function authorizeOAuth($originUrl)
42611 {
42612 if ($originUrl !== 'bitbucket.org') {
42613 return false;
42614 }
42615
42616
42617 if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
42618 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
42619
42620 return true;
42621 }
42622
42623 return false;
42624 }
42625
42626
42627
42628
42629
42630 private function requestAccessToken($originUrl)
42631 {
42632 try {
42633 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
42634 'retry-auth-failure' => false,
42635 'http' => array(
42636 'method' => 'POST',
42637 'content' => 'grant_type=client_credentials',
42638 ),
42639 ));
42640
42641 $this->token = json_decode($json, true);
42642 } catch (TransportException $e) {
42643 if ($e->getCode() === 400) {
42644 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
42645 $this->io->writeError('This can have two reasons:');
42646 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
42647 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
42648
42649 return false;
42650 } elseif (in_array($e->getCode(), array(403, 401))) {
42651 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
42652 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
42653
42654 return false;
42655 }
42656
42657 throw $e;
42658 }
42659
42660 return true;
42661 }
42662
42663
42664
42665
42666
42667
42668
42669
42670
42671
42672 public function authorizeOAuthInteractively($originUrl, $message = null)
42673 {
42674 if ($message) {
42675 $this->io->writeError($message);
42676 }
42677
42678 $url = 'https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/';
42679 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
42680 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
42681 $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)');
42682
42683 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
42684
42685 if (!$consumerKey) {
42686 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
42687 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
42688
42689 return false;
42690 }
42691
42692 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
42693
42694 if (!$consumerSecret) {
42695 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
42696 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
42697
42698 return false;
42699 }
42700
42701 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
42702
42703 if (!$this->requestAccessToken($originUrl)) {
42704 return false;
42705 }
42706
42707
42708 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
42709
42710
42711 $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
42712
42713 $this->io->writeError('<info>Consumer stored successfully.</info>');
42714
42715 return true;
42716 }
42717
42718
42719
42720
42721
42722
42723
42724
42725
42726 public function requestToken($originUrl, $consumerKey, $consumerSecret)
42727 {
42728 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
42729 return $this->token['access_token'];
42730 }
42731
42732 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
42733 if (!$this->requestAccessToken($originUrl)) {
42734 return '';
42735 }
42736
42737 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
42738
42739 return $this->token['access_token'];
42740 }
42741
42742
42743
42744
42745
42746
42747
42748 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
42749 {
42750 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
42751
42752 $time = null === $this->time ? time() : $this->time;
42753 $consumer = array(
42754 "consumer-key" => $consumerKey,
42755 "consumer-secret" => $consumerSecret,
42756 "access-token" => $this->token['access_token'],
42757 "access-token-expiration" => $time + $this->token['expires_in'],
42758 );
42759
42760 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
42761 }
42762
42763
42764
42765
42766
42767 private function getTokenFromConfig($originUrl)
42768 {
42769 $authConfig = $this->config->get('bitbucket-oauth');
42770
42771 if (
42772 !isset($authConfig[$originUrl]['access-token'])
42773 || !isset($authConfig[$originUrl]['access-token-expiration'])
42774 || time() > $authConfig[$originUrl]['access-token-expiration']
42775 ) {
42776 return false;
42777 }
42778
42779 $this->token = array(
42780 'access_token' => $authConfig[$originUrl]['access-token'],
42781 );
42782
42783 return true;
42784 }
42785 }
42786 <?php
42787
42788
42789
42790
42791
42792
42793
42794
42795
42796
42797
42798 namespace Composer\Util;
42799
42800
42801
42802
42803
42804
42805 class ComposerMirror
42806 {
42807 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
42808 {
42809 if ($reference) {
42810 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
42811 }
42812 $version = strpos($version, '/') === false ? $version : md5($version);
42813
42814 return str_replace(
42815 array('%package%', '%version%', '%reference%', '%type%'),
42816 array($packageName, $version, $reference, $type),
42817 $mirrorUrl
42818 );
42819 }
42820
42821 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
42822 {
42823 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
42824 $url = 'gh-'.$match[1].'/'.$match[2];
42825 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
42826 $url = 'bb-'.$match[1].'/'.$match[2];
42827 } else {
42828 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
42829 }
42830
42831 return str_replace(
42832 array('%package%', '%normalizedUrl%', '%type%'),
42833 array($packageName, $url, $type),
42834 $mirrorUrl
42835 );
42836 }
42837
42838 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
42839 {
42840 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
42841 }
42842 }
42843 <?php
42844
42845
42846
42847
42848
42849
42850
42851
42852
42853
42854
42855 namespace Composer\Util;
42856
42857 use Composer\Package\Loader\ArrayLoader;
42858 use Composer\Package\Loader\ValidatingArrayLoader;
42859 use Composer\Package\Loader\InvalidPackageException;
42860 use Composer\Json\JsonValidationException;
42861 use Composer\IO\IOInterface;
42862 use Composer\Json\JsonFile;
42863 use Composer\Spdx\SpdxLicenses;
42864
42865
42866
42867
42868
42869
42870
42871 class ConfigValidator
42872 {
42873 private $io;
42874
42875 public function __construct(IOInterface $io)
42876 {
42877 $this->io = $io;
42878 }
42879
42880
42881
42882
42883
42884
42885
42886
42887
42888 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
42889 {
42890 $errors = array();
42891 $publishErrors = array();
42892 $warnings = array();
42893
42894
42895 $laxValid = false;
42896 try {
42897 $json = new JsonFile($file, null, $this->io);
42898 $manifest = $json->read();
42899
42900 $json->validateSchema(JsonFile::LAX_SCHEMA);
42901 $laxValid = true;
42902 $json->validateSchema();
42903 } catch (JsonValidationException $e) {
42904 foreach ($e->getErrors() as $message) {
42905 if ($laxValid) {
42906 $publishErrors[] = $message;
42907 } else {
42908 $errors[] = $message;
42909 }
42910 }
42911 } catch (\Exception $e) {
42912 $errors[] = $e->getMessage();
42913
42914 return array($errors, $publishErrors, $warnings);
42915 }
42916
42917
42918 if (empty($manifest['license'])) {
42919 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
42920 } else {
42921 $licenses = (array) $manifest['license'];
42922
42923
42924 foreach ($licenses as $key => $license) {
42925 if ('proprietary' === $license) {
42926 unset($licenses[$key]);
42927 }
42928 }
42929
42930 $licenseValidator = new SpdxLicenses();
42931 foreach ($licenses as $license) {
42932 $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
42933 if ($spdxLicense && $spdxLicense[3]) {
42934 if (preg_match('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) {
42935 $warnings[] = sprintf(
42936 'License "%s" is a deprecated SPDX license identifier, use "'.str_replace('+', '', $license).'-or-later" instead',
42937 $license
42938 );
42939 } elseif (preg_match('{^[AL]?GPL-[123](\.[01])?$}i', $license)) {
42940 $warnings[] = sprintf(
42941 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead',
42942 $license
42943 );
42944 } else {
42945 $warnings[] = sprintf(
42946 'License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/',
42947 $license
42948 );
42949 }
42950 }
42951 }
42952 }
42953
42954 if (isset($manifest['version'])) {
42955 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
42956 }
42957
42958 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
42959 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
42960 $suggestName = strtolower($suggestName);
42961
42962 $publishErrors[] = sprintf(
42963 '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.',
42964 $manifest['name'],
42965 $suggestName
42966 );
42967 }
42968
42969 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
42970 $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.";
42971 }
42972
42973
42974 if (isset($manifest['require']) && isset($manifest['require-dev'])) {
42975 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
42976
42977 if (!empty($requireOverrides)) {
42978 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
42979 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
42980 }
42981 }
42982
42983
42984
42985 foreach (array('provide', 'replace') as $linkType) {
42986 if (isset($manifest[$linkType])) {
42987 foreach (array('require', 'require-dev') as $requireType) {
42988 if (isset($manifest[$requireType])) {
42989 foreach ($manifest[$linkType] as $provide => $constraint) {
42990 if (isset($manifest[$requireType][$provide])) {
42991 $warnings[] = 'The package ' . $provide . ' in '.$requireType.' is also listed in '.$linkType.' which satisfies the requirement. Remove it from '.$linkType.' if you wish to install it.';
42992 }
42993 }
42994 }
42995 }
42996 }
42997 }
42998
42999
43000 $require = isset($manifest['require']) ? $manifest['require'] : array();
43001 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
43002 $packages = array_merge($require, $requireDev);
43003 foreach ($packages as $package => $version) {
43004 if (preg_match('/#/', $version) === 1) {
43005 $warnings[] = sprintf(
43006 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
43007 $package
43008 );
43009 }
43010 }
43011
43012
43013 $scriptsDescriptions = isset($manifest['scripts-descriptions']) ? $manifest['scripts-descriptions'] : array();
43014 $scripts = isset($manifest['scripts']) ? $manifest['scripts'] : array();
43015 foreach ($scriptsDescriptions as $scriptName => $scriptDescription) {
43016 if (!array_key_exists($scriptName, $scripts)) {
43017 $warnings[] = sprintf(
43018 'Description for non-existent script "%s" found in "scripts-descriptions"',
43019 $scriptName
43020 );
43021 }
43022 }
43023
43024
43025 if (isset($manifest['autoload']['psr-0'][''])) {
43026 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
43027 }
43028 if (isset($manifest['autoload']['psr-4'][''])) {
43029 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
43030 }
43031
43032 try {
43033 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
43034 if (!isset($manifest['version'])) {
43035 $manifest['version'] = '1.0.0';
43036 }
43037 if (!isset($manifest['name'])) {
43038 $manifest['name'] = 'dummy/dummy';
43039 }
43040 $loader->load($manifest);
43041 } catch (InvalidPackageException $e) {
43042 $errors = array_merge($errors, $e->getErrors());
43043 }
43044
43045 $warnings = array_merge($warnings, $loader->getWarnings());
43046
43047 return array($errors, $publishErrors, $warnings);
43048 }
43049 }
43050 <?php
43051
43052
43053
43054
43055
43056
43057
43058
43059
43060
43061
43062 namespace Composer\Util;
43063
43064 use Composer\IO\IOInterface;
43065
43066
43067
43068
43069
43070
43071 class ErrorHandler
43072 {
43073 private static $io;
43074
43075
43076
43077
43078
43079
43080
43081
43082
43083
43084
43085
43086
43087 public static function handle($level, $message, $file, $line)
43088 {
43089
43090 if (!(error_reporting() & $level)) {
43091 return;
43092 }
43093
43094 if (filter_var(ini_get('xdebug.scream'), FILTER_VALIDATE_BOOLEAN)) {
43095 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
43096 "\na legitimately suppressed error that you were not supposed to see.";
43097 }
43098
43099 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
43100 throw new \ErrorException($message, 0, $level, $file, $line);
43101 }
43102
43103 if (self::$io) {
43104
43105
43106 if (preg_match('{^Return type of (Symfony|Composer)\\\\.*ReturnTypeWillChange}is', $message)) {
43107 return true;
43108 }
43109 if (strpos(strtr($file, '\\', '/'), 'vendor/symfony/') !== false) {
43110 return true;
43111 }
43112
43113 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
43114 if (self::$io->isVerbose()) {
43115 self::$io->writeError('<warning>Stack trace:</warning>');
43116 self::$io->writeError(array_filter(array_map(function ($a) {
43117 if (isset($a['line'], $a['file'])) {
43118 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
43119 }
43120
43121 return null;
43122 }, array_slice(debug_backtrace(), 2))));
43123 }
43124 }
43125
43126 return true;
43127 }
43128
43129
43130
43131
43132
43133
43134 public static function register(IOInterface $io = null)
43135 {
43136 set_error_handler(array(__CLASS__, 'handle'));
43137 error_reporting(E_ALL | E_STRICT);
43138 self::$io = $io;
43139 }
43140 }
43141 <?php
43142
43143
43144
43145
43146
43147
43148
43149
43150
43151
43152
43153 namespace Composer\Util;
43154
43155 use RecursiveDirectoryIterator;
43156 use RecursiveIteratorIterator;
43157 use Symfony\Component\Filesystem\Exception\IOException;
43158 use Symfony\Component\Finder\Finder;
43159
43160
43161
43162
43163
43164 class Filesystem
43165 {
43166 private $processExecutor;
43167
43168 public function __construct(ProcessExecutor $executor = null)
43169 {
43170 $this->processExecutor = $executor ?: new ProcessExecutor();
43171 }
43172
43173 public function remove($file)
43174 {
43175 if (is_dir($file)) {
43176 return $this->removeDirectory($file);
43177 }
43178
43179 if (file_exists($file)) {
43180 return $this->unlink($file);
43181 }
43182
43183 return false;
43184 }
43185
43186
43187
43188
43189
43190
43191
43192 public function isDirEmpty($dir)
43193 {
43194 $finder = Finder::create()
43195 ->ignoreVCS(false)
43196 ->ignoreDotFiles(false)
43197 ->depth(0)
43198 ->in($dir);
43199
43200 return count($finder) === 0;
43201 }
43202
43203 public function emptyDirectory($dir, $ensureDirectoryExists = true)
43204 {
43205 if (file_exists($dir) && is_link($dir)) {
43206 $this->unlink($dir);
43207 }
43208
43209 if ($ensureDirectoryExists) {
43210 $this->ensureDirectoryExists($dir);
43211 }
43212
43213 if (is_dir($dir)) {
43214 $finder = Finder::create()
43215 ->ignoreVCS(false)
43216 ->ignoreDotFiles(false)
43217 ->depth(0)
43218 ->in($dir);
43219
43220 foreach ($finder as $path) {
43221 $this->remove((string) $path);
43222 }
43223 }
43224 }
43225
43226
43227
43228
43229
43230
43231
43232
43233
43234
43235
43236 public function removeDirectory($directory)
43237 {
43238 if ($this->isSymlinkedDirectory($directory)) {
43239 return $this->unlinkSymlinkedDirectory($directory);
43240 }
43241
43242 if ($this->isJunction($directory)) {
43243 return $this->removeJunction($directory);
43244 }
43245
43246 if (is_link($directory)) {
43247 return unlink($directory);
43248 }
43249
43250 if (!file_exists($directory) || !is_dir($directory)) {
43251 return true;
43252 }
43253
43254 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
43255 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
43256 }
43257
43258 if (!function_exists('proc_open')) {
43259 return $this->removeDirectoryPhp($directory);
43260 }
43261
43262 if (Platform::isWindows()) {
43263 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
43264 } else {
43265 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
43266 }
43267
43268 $result = $this->getProcess()->execute($cmd, $output) === 0;
43269
43270
43271 clearstatcache();
43272
43273 if ($result && !file_exists($directory)) {
43274 return true;
43275 }
43276
43277 return $this->removeDirectoryPhp($directory);
43278 }
43279
43280
43281
43282
43283
43284
43285
43286
43287
43288
43289
43290 public function removeDirectoryPhp($directory)
43291 {
43292 try {
43293 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
43294 } catch (\UnexpectedValueException $e) {
43295
43296
43297 clearstatcache();
43298 usleep(100000);
43299 if (!is_dir($directory)) {
43300 return true;
43301 }
43302 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
43303 }
43304 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
43305
43306 foreach ($ri as $file) {
43307 if ($file->isDir()) {
43308 $this->rmdir($file->getPathname());
43309 } else {
43310 $this->unlink($file->getPathname());
43311 }
43312 }
43313
43314 return $this->rmdir($directory);
43315 }
43316
43317 public function ensureDirectoryExists($directory)
43318 {
43319 if (!is_dir($directory)) {
43320 if (file_exists($directory)) {
43321 throw new \RuntimeException(
43322 $directory.' exists and is not a directory.'
43323 );
43324 }
43325 if (!@mkdir($directory, 0777, true)) {
43326 throw new \RuntimeException(
43327 $directory.' does not exist and could not be created.'
43328 );
43329 }
43330 }
43331 }
43332
43333
43334
43335
43336
43337
43338
43339
43340 public function unlink($path)
43341 {
43342 $unlinked = @$this->unlinkImplementation($path);
43343 if (!$unlinked) {
43344
43345 if (Platform::isWindows()) {
43346 usleep(350000);
43347 $unlinked = @$this->unlinkImplementation($path);
43348 }
43349
43350 if (!$unlinked) {
43351 $error = error_get_last();
43352 $message = 'Could not delete '.$path.': ' . @$error['message'];
43353 if (Platform::isWindows()) {
43354 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
43355 }
43356
43357 throw new \RuntimeException($message);
43358 }
43359 }
43360
43361 return true;
43362 }
43363
43364
43365
43366
43367
43368
43369
43370
43371 public function rmdir($path)
43372 {
43373 $deleted = @rmdir($path);
43374 if (!$deleted) {
43375
43376 if (Platform::isWindows()) {
43377 usleep(350000);
43378 $deleted = @rmdir($path);
43379 }
43380
43381 if (!$deleted) {
43382 $error = error_get_last();
43383 $message = 'Could not delete '.$path.': ' . @$error['message'];
43384 if (Platform::isWindows()) {
43385 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
43386 }
43387
43388 throw new \RuntimeException($message);
43389 }
43390 }
43391
43392 return true;
43393 }
43394
43395
43396
43397
43398
43399
43400
43401
43402
43403
43404 public function copyThenRemove($source, $target)
43405 {
43406 $this->copy($source, $target);
43407 if (!is_dir($source)) {
43408 $this->unlink($source);
43409
43410 return;
43411 }
43412
43413 $this->removeDirectoryPhp($source);
43414 }
43415
43416
43417
43418
43419
43420
43421
43422
43423 public function copy($source, $target)
43424 {
43425 if (!is_dir($source)) {
43426 return copy($source, $target);
43427 }
43428
43429 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
43430 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
43431 $this->ensureDirectoryExists($target);
43432
43433 $result = true;
43434 foreach ($ri as $file) {
43435 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
43436 if ($file->isDir()) {
43437 $this->ensureDirectoryExists($targetPath);
43438 } else {
43439 $result = $result && copy($file->getPathname(), $targetPath);
43440 }
43441 }
43442
43443 return $result;
43444 }
43445
43446 public function rename($source, $target)
43447 {
43448 if (true === @rename($source, $target)) {
43449 return;
43450 }
43451
43452 if (!function_exists('proc_open')) {
43453 $this->copyThenRemove($source, $target);
43454
43455 return;
43456 }
43457
43458 if (Platform::isWindows()) {
43459
43460 $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
43461 $result = $this->processExecutor->execute($command, $output);
43462
43463
43464 clearstatcache();
43465
43466 if (0 === $result) {
43467 $this->remove($source);
43468
43469 return;
43470 }
43471 } else {
43472
43473
43474 $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
43475 $result = $this->processExecutor->execute($command, $output);
43476
43477
43478 clearstatcache();
43479
43480 if (0 === $result) {
43481 return;
43482 }
43483 }
43484
43485 $this->copyThenRemove($source, $target);
43486 }
43487
43488
43489
43490
43491
43492
43493
43494
43495
43496
43497 public function findShortestPath($from, $to, $directories = false)
43498 {
43499 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
43500 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
43501 }
43502
43503 $from = lcfirst($this->normalizePath($from));
43504 $to = lcfirst($this->normalizePath($to));
43505
43506 if ($directories) {
43507 $from = rtrim($from, '/') . '/dummy_file';
43508 }
43509
43510 if (dirname($from) === dirname($to)) {
43511 return './'.basename($to);
43512 }
43513
43514 $commonPath = $to;
43515 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
43516 $commonPath = strtr(dirname($commonPath), '\\', '/');
43517 }
43518
43519 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
43520 return $to;
43521 }
43522
43523 $commonPath = rtrim($commonPath, '/') . '/';
43524 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
43525 $commonPathCode = str_repeat('../', $sourcePathDepth);
43526
43527 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
43528 }
43529
43530
43531
43532
43533
43534
43535
43536
43537
43538
43539
43540 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
43541 {
43542 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
43543 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
43544 }
43545
43546 $from = lcfirst($this->normalizePath($from));
43547 $to = lcfirst($this->normalizePath($to));
43548
43549 if ($from === $to) {
43550 return $directories ? '__DIR__' : '__FILE__';
43551 }
43552
43553 $commonPath = $to;
43554 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
43555 $commonPath = strtr(dirname($commonPath), '\\', '/');
43556 }
43557
43558 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
43559 return var_export($to, true);
43560 }
43561
43562 $commonPath = rtrim($commonPath, '/') . '/';
43563 if (strpos($to, $from.'/') === 0) {
43564 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
43565 }
43566 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
43567 if ($staticCode) {
43568 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
43569 } else {
43570 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
43571 }
43572 $relTarget = substr($to, strlen($commonPath));
43573
43574 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
43575 }
43576
43577
43578
43579
43580
43581
43582
43583 public function isAbsolutePath($path)
43584 {
43585 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':' || substr($path, 0, 2) === '\\\\';
43586 }
43587
43588
43589
43590
43591
43592
43593
43594
43595
43596 public function size($path)
43597 {
43598 if (!file_exists($path)) {
43599 throw new \RuntimeException("$path does not exist.");
43600 }
43601 if (is_dir($path)) {
43602 return $this->directorySize($path);
43603 }
43604
43605 return filesize($path);
43606 }
43607
43608
43609
43610
43611
43612
43613
43614
43615 public function normalizePath($path)
43616 {
43617 $parts = array();
43618 $path = strtr($path, '\\', '/');
43619 $prefix = '';
43620 $absolute = false;
43621
43622
43623 if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
43624 $prefix = $match[1];
43625 $path = substr($path, strlen($prefix));
43626 }
43627
43628 if (substr($path, 0, 1) === '/') {
43629 $absolute = true;
43630 $path = substr($path, 1);
43631 }
43632
43633 $up = false;
43634 foreach (explode('/', $path) as $chunk) {
43635 if ('..' === $chunk && ($absolute || $up)) {
43636 array_pop($parts);
43637 $up = !(empty($parts) || '..' === end($parts));
43638 } elseif ('.' !== $chunk && '' !== $chunk) {
43639 $parts[] = $chunk;
43640 $up = '..' !== $chunk;
43641 }
43642 }
43643
43644 return $prefix.($absolute ? '/' : '').implode('/', $parts);
43645 }
43646
43647
43648
43649
43650
43651
43652
43653 public static function isLocalPath($path)
43654 {
43655 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
43656 }
43657
43658 public static function getPlatformPath($path)
43659 {
43660 if (Platform::isWindows()) {
43661 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
43662 }
43663
43664 return preg_replace('{^file://}i', '', $path);
43665 }
43666
43667 protected function directorySize($directory)
43668 {
43669 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
43670 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
43671
43672 $size = 0;
43673 foreach ($ri as $file) {
43674 if ($file->isFile()) {
43675 $size += $file->getSize();
43676 }
43677 }
43678
43679 return $size;
43680 }
43681
43682 protected function getProcess()
43683 {
43684 return $this->processExecutor;
43685 }
43686
43687
43688
43689
43690
43691
43692
43693
43694
43695
43696 private function unlinkImplementation($path)
43697 {
43698 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
43699 return rmdir($path);
43700 }
43701
43702 return unlink($path);
43703 }
43704
43705
43706
43707
43708
43709
43710
43711
43712 public function relativeSymlink($target, $link)
43713 {
43714 $cwd = getcwd();
43715
43716 $relativePath = $this->findShortestPath($link, $target);
43717 chdir(dirname($link));
43718 $result = @symlink($relativePath, $link);
43719
43720 chdir($cwd);
43721
43722 return $result;
43723 }
43724
43725
43726
43727
43728
43729
43730
43731
43732 public function isSymlinkedDirectory($directory)
43733 {
43734 if (!is_dir($directory)) {
43735 return false;
43736 }
43737
43738 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
43739
43740 return is_link($resolved);
43741 }
43742
43743
43744
43745
43746
43747
43748 private function unlinkSymlinkedDirectory($directory)
43749 {
43750 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
43751
43752 return $this->unlink($resolved);
43753 }
43754
43755
43756
43757
43758
43759
43760
43761
43762 private function resolveSymlinkedDirectorySymlink($pathname)
43763 {
43764 if (!is_dir($pathname)) {
43765 return $pathname;
43766 }
43767
43768 $resolved = rtrim($pathname, '/');
43769
43770 if (!strlen($resolved)) {
43771 return $pathname;
43772 }
43773
43774 return $resolved;
43775 }
43776
43777
43778
43779
43780
43781
43782
43783 public function junction($target, $junction)
43784 {
43785 if (!Platform::isWindows()) {
43786 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
43787 }
43788 if (!is_dir($target)) {
43789 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
43790 }
43791 $cmd = sprintf(
43792 'mklink /J %s %s',
43793 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
43794 ProcessExecutor::escape(realpath($target))
43795 );
43796 if ($this->getProcess()->execute($cmd, $output) !== 0) {
43797 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
43798 }
43799 clearstatcache(true, $junction);
43800 }
43801
43802
43803
43804
43805
43806
43807
43808
43809
43810
43811
43812
43813
43814
43815
43816
43817
43818
43819
43820
43821
43822 public function isJunction($junction)
43823 {
43824 if (!Platform::isWindows()) {
43825 return false;
43826 }
43827
43828
43829 clearstatcache(true, $junction);
43830
43831 if (!is_dir($junction) || is_link($junction)) {
43832 return false;
43833 }
43834
43835 $stat = lstat($junction);
43836
43837
43838 return $stat ? 0x4000 !== ($stat['mode'] & 0xF000) : false;
43839 }
43840
43841
43842
43843
43844
43845
43846
43847 public function removeJunction($junction)
43848 {
43849 if (!Platform::isWindows()) {
43850 return false;
43851 }
43852 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
43853 if (!$this->isJunction($junction)) {
43854 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
43855 }
43856
43857 return $this->rmdir($junction);
43858 }
43859 }
43860 <?php
43861
43862
43863
43864
43865
43866
43867
43868
43869
43870
43871
43872 namespace Composer\Util;
43873
43874 use Composer\Config;
43875 use Composer\IO\IOInterface;
43876
43877
43878
43879
43880 class Git
43881 {
43882 private static $version = false;
43883
43884
43885 protected $io;
43886
43887 protected $config;
43888
43889 protected $process;
43890
43891 protected $filesystem;
43892
43893 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
43894 {
43895 $this->io = $io;
43896 $this->config = $config;
43897 $this->process = $process;
43898 $this->filesystem = $fs;
43899 }
43900
43901 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
43902 {
43903
43904 $this->config->prohibitUrlByConfig($url, $this->io);
43905
43906 if ($initialClone) {
43907 $origCwd = $cwd;
43908 $cwd = null;
43909 }
43910
43911 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
43912 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.');
43913 }
43914
43915 if (!$initialClone) {
43916
43917 $this->process->execute('git remote -v', $output, $cwd);
43918 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) {
43919 $this->io->setAuthentication($match[3], rawurldecode($match[1]), rawurldecode($match[2]));
43920 }
43921 }
43922
43923 $protocols = $this->config->get('github-protocols');
43924 if (!is_array($protocols)) {
43925 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
43926 }
43927
43928 if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
43929 $messages = array();
43930 foreach ($protocols as $protocol) {
43931 if ('ssh' === $protocol) {
43932 $protoUrl = "git@" . $match[1] . ":" . $match[2];
43933 } else {
43934 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
43935 }
43936
43937 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
43938 return;
43939 }
43940 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
43941 if ($initialClone) {
43942 $this->filesystem->removeDirectory($origCwd);
43943 }
43944 }
43945
43946
43947 if (!$this->io->hasAuthentication($match[1]) && !$this->io->isInteractive()) {
43948 $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
43949 }
43950 }
43951
43952
43953 $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
43954
43955 $command = call_user_func($commandCallable, $url);
43956
43957 $auth = null;
43958 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
43959 $errorMsg = $this->process->getErrorOutput();
43960
43961 if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)
43962 || preg_match('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)
43963 ) {
43964 if (!$this->io->hasAuthentication($match[1])) {
43965 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
43966 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
43967
43968 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
43969 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
43970 }
43971 }
43972
43973 if ($this->io->hasAuthentication($match[1])) {
43974 $auth = $this->io->getAuthentication($match[1]);
43975 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
43976 $command = call_user_func($commandCallable, $authUrl);
43977 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43978 return;
43979 }
43980
43981 $errorMsg = $this->process->getErrorOutput();
43982 }
43983 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
43984 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
43985
43986 if (!$this->io->hasAuthentication($match[1])) {
43987 $message = 'Enter your Bitbucket credentials to access private repos';
43988
43989 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
43990 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
43991 $accessToken = $bitbucketUtil->getToken();
43992 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
43993 }
43994 } else { 
43995 $auth = $this->io->getAuthentication($match[1]);
43996
43997
43998 if ($auth['username'] !== 'x-token-auth') {
43999 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
44000 if (! empty($accessToken)) {
44001 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
44002 }
44003 }
44004 }
44005
44006 if ($this->io->hasAuthentication($match[1])) {
44007 $auth = $this->io->getAuthentication($match[1]);
44008 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
44009
44010 $command = call_user_func($commandCallable, $authUrl);
44011 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44012 return;
44013 }
44014
44015 $errorMsg = $this->process->getErrorOutput();
44016 } else { 
44017 $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
44018 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
44019 $command = call_user_func($commandCallable, $sshUrl);
44020 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44021 return;
44022 }
44023
44024 $errorMsg = $this->process->getErrorOutput();
44025 }
44026 } elseif (
44027 preg_match('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?\.git)$}i', $url, $match)
44028 || preg_match('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}', $url, $match)
44029 ) {
44030 if ($match[1] === 'git') {
44031 $match[1] = 'https';
44032 }
44033
44034 if (!$this->io->hasAuthentication($match[2])) {
44035 $gitLabUtil = new GitLab($this->io, $this->config, $this->process);
44036 $message = 'Cloning failed, enter your GitLab credentials to access private repos';
44037
44038 if (!$gitLabUtil->authorizeOAuth($match[2]) && $this->io->isInteractive()) {
44039 $gitLabUtil->authorizeOAuthInteractively($match[1], $match[2], $message);
44040 }
44041 }
44042
44043 if ($this->io->hasAuthentication($match[2])) {
44044 $auth = $this->io->getAuthentication($match[2]);
44045 if ($auth['password'] === 'private-token' || $auth['password'] === 'oauth2' || $auth['password'] === 'gitlab-ci-token') {
44046 $authUrl = $match[1] . '://' . rawurlencode($auth['password']) . ':' . rawurlencode($auth['username']) . '@' . $match[2] . '/' . $match[3]; 
44047 } else {
44048 $authUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . '/' . $match[3];
44049 }
44050
44051 $command = call_user_func($commandCallable, $authUrl);
44052 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44053 return;
44054 }
44055
44056 $errorMsg = $this->process->getErrorOutput();
44057 }
44058 } elseif ($this->isAuthenticationFailure($url, $match)) { 
44059 if (strpos($match[2], '@')) {
44060 list($authParts, $match[2]) = explode('@', $match[2], 2);
44061 }
44062
44063 $storeAuth = false;
44064 if ($this->io->hasAuthentication($match[2])) {
44065 $auth = $this->io->getAuthentication($match[2]);
44066 } elseif ($this->io->isInteractive()) {
44067 $defaultUsername = null;
44068 if (isset($authParts) && $authParts) {
44069 if (false !== strpos($authParts, ':')) {
44070 list($defaultUsername, ) = explode(':', $authParts, 2);
44071 } else {
44072 $defaultUsername = $authParts;
44073 }
44074 }
44075
44076 $this->io->writeError('    Authentication required (<info>' . $match[2] . '</info>):');
44077 $auth = array(
44078 'username' => $this->io->ask('      Username: ', $defaultUsername),
44079 'password' => $this->io->askAndHideAnswer('      Password: '),
44080 );
44081 $storeAuth = $this->config->get('store-auths');
44082 }
44083
44084 if ($auth) {
44085 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
44086
44087 $command = call_user_func($commandCallable, $authUrl);
44088 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44089 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
44090 $authHelper = new AuthHelper($this->io, $this->config);
44091 $authHelper->storeAuth($match[2], $storeAuth);
44092
44093 return;
44094 }
44095
44096 $errorMsg = $this->process->getErrorOutput();
44097 }
44098 }
44099
44100 if ($initialClone) {
44101 $this->filesystem->removeDirectory($origCwd);
44102 }
44103
44104 $this->throwException('Failed to execute ' . $command . "\n\n" . $errorMsg, $url);
44105 }
44106 }
44107
44108 public function syncMirror($url, $dir)
44109 {
44110
44111 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
44112 try {
44113 $commandCallable = function ($url) {
44114 $sanitizedUrl = preg_replace('{://([^@]+?):(.+?)@}', '://', $url);
44115
44116 return sprintf('git remote set-url origin -- %s && git remote update --prune origin && git remote set-url origin -- %s', ProcessExecutor::escape($url), ProcessExecutor::escape($sanitizedUrl));
44117 };
44118 $this->runCommand($commandCallable, $url, $dir);
44119 } catch (\Exception $e) {
44120 $this->io->writeError('<error>Sync mirror failed: ' . $e->getMessage() . '</error>', true, IOInterface::DEBUG);
44121
44122 return false;
44123 }
44124
44125 return true;
44126 }
44127
44128
44129 $this->filesystem->removeDirectory($dir);
44130
44131 $commandCallable = function ($url) use ($dir) {
44132 return sprintf('git clone --mirror -- %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
44133 };
44134
44135 $this->runCommand($commandCallable, $url, $dir, true);
44136
44137 return true;
44138 }
44139
44140 public function fetchRefOrSyncMirror($url, $dir, $ref)
44141 {
44142 if ($this->checkRefIsInMirror($url, $dir, $ref)) {
44143 return true;
44144 }
44145
44146 if ($this->syncMirror($url, $dir)) {
44147 return $this->checkRefIsInMirror($url, $dir, $ref);
44148 }
44149
44150 return false;
44151 }
44152
44153 public static function getNoShowSignatureFlag(ProcessExecutor $process)
44154 {
44155 $gitVersion = self::getVersion($process);
44156 if ($gitVersion && version_compare($gitVersion, '2.10.0-rc0', '>=')) {
44157 return ' --no-show-signature';
44158 }
44159
44160 return '';
44161 }
44162
44163 private function checkRefIsInMirror($url, $dir, $ref)
44164 {
44165 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
44166 $escapedRef = ProcessExecutor::escape($ref.'^{commit}');
44167 $exitCode = $this->process->execute(sprintf('git rev-parse --quiet --verify %s', $escapedRef), $ignoredOutput, $dir);
44168 if ($exitCode === 0) {
44169 return true;
44170 }
44171 }
44172
44173 return false;
44174 }
44175
44176 private function isAuthenticationFailure($url, &$match)
44177 {
44178 if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
44179 return false;
44180 }
44181
44182 $authFailures = array(
44183 'fatal: Authentication failed',
44184 'remote error: Invalid username or password.',
44185 'error: 401 Unauthorized',
44186 'fatal: unable to access',
44187 'fatal: could not read Username',
44188 );
44189
44190 $errorOutput = $this->process->getErrorOutput();
44191 foreach ($authFailures as $authFailure) {
44192 if (strpos($errorOutput, $authFailure) !== false) {
44193 return true;
44194 }
44195 }
44196
44197 return false;
44198 }
44199
44200 public static function cleanEnv()
44201 {
44202 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
44203 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');
44204 }
44205
44206
44207 if (getenv('GIT_ASKPASS') !== 'echo') {
44208 putenv('GIT_ASKPASS=echo');
44209 $_SERVER['GIT_ASKPASS'] = 'echo';
44210 }
44211
44212
44213 if (getenv('GIT_DIR')) {
44214 putenv('GIT_DIR');
44215 unset($_SERVER['GIT_DIR']);
44216 }
44217 if (getenv('GIT_WORK_TREE')) {
44218 putenv('GIT_WORK_TREE');
44219 unset($_SERVER['GIT_WORK_TREE']);
44220 }
44221
44222
44223 if (getenv('LANGUAGE') !== 'C') {
44224 putenv('LANGUAGE=C');
44225 $_SERVER['LANGUAGE'] = 'C';
44226 }
44227
44228
44229 putenv("DYLD_LIBRARY_PATH");
44230 unset($_SERVER['DYLD_LIBRARY_PATH']);
44231 }
44232
44233 public static function getGitHubDomainsRegex(Config $config)
44234 {
44235 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
44236 }
44237
44238 public static function getGitLabDomainsRegex(Config $config)
44239 {
44240 return '(' . implode('|', array_map('preg_quote', $config->get('gitlab-domains'))) . ')';
44241 }
44242
44243 public static function sanitizeUrl($message)
44244 {
44245 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
44246 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
44247 return '://***:***@';
44248 }
44249
44250 return '://' . $m[1] . ':***@';
44251 }, $message);
44252 }
44253
44254 private function throwException($message, $url)
44255 {
44256
44257 clearstatcache();
44258
44259 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
44260 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()));
44261 }
44262
44263 throw new \RuntimeException(self::sanitizeUrl($message));
44264 }
44265
44266
44267
44268
44269
44270
44271 public static function getVersion(ProcessExecutor $process = null)
44272 {
44273 if (false === self::$version) {
44274 self::$version = null;
44275 if (!$process) {
44276 $process = new ProcessExecutor;
44277 }
44278 if (0 === $process->execute('git --version', $output) && preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
44279 self::$version = $matches[1];
44280 }
44281 }
44282
44283 return self::$version;
44284 }
44285 }
44286 <?php
44287
44288
44289
44290
44291
44292
44293
44294
44295
44296
44297
44298 namespace Composer\Util;
44299
44300 use Composer\Factory;
44301 use Composer\IO\IOInterface;
44302 use Composer\Config;
44303 use Composer\Downloader\TransportException;
44304
44305
44306
44307
44308 class GitHub
44309 {
44310 protected $io;
44311 protected $config;
44312 protected $process;
44313 protected $remoteFilesystem;
44314
44315
44316
44317
44318
44319
44320
44321
44322
44323 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
44324 {
44325 $this->io = $io;
44326 $this->config = $config;
44327 $this->process = $process ?: new ProcessExecutor($io);
44328 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
44329 }
44330
44331
44332
44333
44334
44335
44336
44337 public function authorizeOAuth($originUrl)
44338 {
44339 if (!in_array($originUrl, $this->config->get('github-domains'))) {
44340 return false;
44341 }
44342
44343
44344 if (0 === $this->process->execute('git config github.accesstoken', $output)) {
44345 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
44346
44347 return true;
44348 }
44349
44350 return false;
44351 }
44352
44353
44354
44355
44356
44357
44358
44359
44360
44361
44362 public function authorizeOAuthInteractively($originUrl, $message = null)
44363 {
44364 if ($message) {
44365 $this->io->writeError($message);
44366 }
44367
44368 $note = 'Composer';
44369 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
44370 $note .= ' on ' . trim($output);
44371 }
44372 $note .= ' ' . date('Y-m-d Hi');
44373
44374 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
44375 $this->io->writeError(sprintf('Head to %s', $url));
44376 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
44377
44378 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
44379
44380 if (!$token) {
44381 $this->io->writeError('<warning>No token given, aborting.</warning>');
44382 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
44383
44384 return false;
44385 }
44386
44387 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
44388
44389 try {
44390 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
44391
44392 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
44393 'retry-auth-failure' => false,
44394 ));
44395 } catch (TransportException $e) {
44396 if (in_array($e->getCode(), array(403, 401))) {
44397 $this->io->writeError('<error>Invalid token provided.</error>');
44398 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
44399
44400 return false;
44401 }
44402
44403 throw $e;
44404 }
44405
44406
44407 $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
44408 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
44409
44410 $this->io->writeError('<info>Token stored successfully.</info>');
44411
44412 return true;
44413 }
44414
44415
44416
44417
44418
44419
44420
44421
44422 public function getRateLimit(array $headers)
44423 {
44424 $rateLimit = array(
44425 'limit' => '?',
44426 'reset' => '?',
44427 );
44428
44429 foreach ($headers as $header) {
44430 $header = trim($header);
44431 if (false === strpos($header, 'X-RateLimit-')) {
44432 continue;
44433 }
44434 list($type, $value) = explode(':', $header, 2);
44435 switch ($type) {
44436 case 'X-RateLimit-Limit':
44437 $rateLimit['limit'] = (int) trim($value);
44438 break;
44439 case 'X-RateLimit-Reset':
44440 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
44441 break;
44442 }
44443 }
44444
44445 return $rateLimit;
44446 }
44447
44448
44449
44450
44451
44452
44453
44454
44455 public function isRateLimited(array $headers)
44456 {
44457 foreach ($headers as $header) {
44458 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
44459 return true;
44460 }
44461 }
44462
44463 return false;
44464 }
44465 }
44466 <?php
44467
44468
44469
44470
44471
44472
44473
44474
44475
44476
44477
44478 namespace Composer\Util;
44479
44480 use Composer\IO\IOInterface;
44481 use Composer\Config;
44482 use Composer\Factory;
44483 use Composer\Downloader\TransportException;
44484 use Composer\Json\JsonFile;
44485
44486
44487
44488
44489 class GitLab
44490 {
44491 protected $io;
44492 protected $config;
44493 protected $process;
44494 protected $remoteFilesystem;
44495
44496
44497
44498
44499
44500
44501
44502
44503
44504 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
44505 {
44506 $this->io = $io;
44507 $this->config = $config;
44508 $this->process = $process ?: new ProcessExecutor($io);
44509 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
44510 }
44511
44512
44513
44514
44515
44516
44517
44518
44519 public function authorizeOAuth($originUrl)
44520 {
44521
44522 $bcOriginUrl = preg_replace('{:\d+}', '', $originUrl);
44523
44524 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true) && !in_array($bcOriginUrl, $this->config->get('gitlab-domains'), true)) {
44525 return false;
44526 }
44527
44528
44529 if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
44530 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
44531
44532 return true;
44533 }
44534
44535
44536 $authTokens = $this->config->get('gitlab-token');
44537
44538 if (isset($authTokens[$originUrl])) {
44539 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
44540
44541 return true;
44542 }
44543
44544 if (isset($authTokens[$bcOriginUrl])) {
44545 $this->io->setAuthentication($originUrl, $authTokens[$bcOriginUrl], 'private-token');
44546
44547 return true;
44548 }
44549
44550 return false;
44551 }
44552
44553
44554
44555
44556
44557
44558
44559
44560
44561
44562
44563
44564
44565 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
44566 {
44567 if ($message) {
44568 $this->io->writeError($message);
44569 }
44570
44571 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
44572 $this->io->writeError('To revoke access to this token you can visit '.$scheme.'://'.$originUrl.'/profile/applications');
44573
44574 $attemptCounter = 0;
44575
44576 while ($attemptCounter++ < 5) {
44577 try {
44578 $response = $this->createToken($scheme, $originUrl);
44579 } catch (TransportException $e) {
44580
44581
44582 if (in_array($e->getCode(), array(403, 401))) {
44583 if (401 === $e->getCode()) {
44584 $response = json_decode($e->getResponse(), true);
44585 if (isset($response['error']) && $response['error'] === 'invalid_grant') {
44586 $this->io->writeError('Bad credentials. If you have two factor authentication enabled you will have to manually create a personal access token');
44587 } else {
44588 $this->io->writeError('Bad credentials.');
44589 }
44590 } else {
44591 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
44592 }
44593
44594 $this->io->writeError('You can also manually create a personal access token enabling the "read_api" scope at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
44595 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
44596
44597 continue;
44598 }
44599
44600 throw $e;
44601 }
44602
44603 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
44604
44605
44606 $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
44607
44608 return true;
44609 }
44610
44611 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
44612 }
44613
44614 private function createToken($scheme, $originUrl)
44615 {
44616 $username = $this->io->ask('Username: ');
44617 $password = $this->io->askAndHideAnswer('Password: ');
44618
44619 $headers = array('Content-Type: application/x-www-form-urlencoded');
44620
44621 $apiUrl = $originUrl;
44622 $data = http_build_query(array(
44623 'username' => $username,
44624 'password' => $password,
44625 'grant_type' => 'password',
44626 ), null, '&');
44627 $options = array(
44628 'retry-auth-failure' => false,
44629 'http' => array(
44630 'method' => 'POST',
44631 'header' => $headers,
44632 'content' => $data,
44633 ),
44634 );
44635
44636 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
44637
44638 $this->io->writeError('Token successfully created');
44639
44640 return JsonFile::parseJson($json);
44641 }
44642 }
44643 <?php
44644
44645
44646
44647
44648
44649
44650
44651
44652
44653
44654
44655 namespace Composer\Util;
44656
44657 use Composer\Config;
44658 use Composer\IO\IOInterface;
44659
44660
44661
44662
44663 class Hg
44664 {
44665
44666
44667
44668 private $io;
44669
44670
44671
44672
44673 private $config;
44674
44675
44676
44677
44678 private $process;
44679
44680 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process)
44681 {
44682 $this->io = $io;
44683 $this->config = $config;
44684 $this->process = $process;
44685 }
44686
44687 public function runCommand($commandCallable, $url, $cwd)
44688 {
44689 $this->config->prohibitUrlByConfig($url, $this->io);
44690
44691
44692 $command = call_user_func($commandCallable, $url);
44693
44694 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44695 return;
44696 }
44697
44698
44699 if (preg_match('{^(https?)://((.+)(?:\:(.+))?@)?([^/]+)(/.*)?}mi', $url, $match) && $this->io->hasAuthentication($match[5])) {
44700 $auth = $this->io->getAuthentication($match[5]);
44701 $authenticatedUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[5] . (!empty($match[6]) ? $match[6] : null);
44702
44703 $command = call_user_func($commandCallable, $authenticatedUrl);
44704
44705 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44706 return;
44707 }
44708
44709 $error = $this->process->getErrorOutput();
44710 } else {
44711 $error = 'The given URL (' . $url . ') does not match the required format (http(s)://(username:password@)example.com/path-to-repository)';
44712 }
44713
44714 $this->throwException('Failed to clone ' . $url . ', ' . "\n\n" . $error, $url);
44715 }
44716
44717 public static function sanitizeUrl($message)
44718 {
44719 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
44720 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
44721 return '://***:***@';
44722 }
44723
44724 return '://' . $m[1] . ':***@';
44725 }, $message);
44726 }
44727
44728 private function throwException($message, $url)
44729 {
44730 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
44731 throw new \RuntimeException(self::sanitizeUrl('Failed to clone ' . $url . ', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()));
44732 }
44733
44734 throw new \RuntimeException(self::sanitizeUrl($message));
44735 }
44736 }
44737 <?php
44738
44739
44740
44741
44742
44743
44744
44745
44746
44747
44748
44749 namespace Composer\Util;
44750
44751 use Composer\XdebugHandler\XdebugHandler;
44752
44753
44754
44755
44756
44757
44758
44759
44760 class IniHelper
44761 {
44762
44763
44764
44765
44766
44767
44768
44769
44770 public static function getAll()
44771 {
44772 return XdebugHandler::getAllIniFiles();
44773 }
44774
44775
44776
44777
44778
44779
44780 public static function getMessage()
44781 {
44782 $paths = self::getAll();
44783
44784 if (empty($paths[0])) {
44785 array_shift($paths);
44786 }
44787
44788 $ini = array_shift($paths);
44789
44790 if (empty($ini)) {
44791 return 'A php.ini file does not exist. You will have to create one.';
44792 }
44793
44794 if (!empty($paths)) {
44795 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
44796 }
44797
44798 return 'The php.ini used by your command-line PHP is: '.$ini;
44799 }
44800 }
44801 <?php
44802
44803
44804
44805
44806
44807
44808
44809
44810
44811
44812
44813 namespace Composer\Util;
44814
44815 use stdClass;
44816
44817
44818
44819
44820 class NoProxyPattern
44821 {
44822
44823
44824
44825 protected $hostNames = array();
44826
44827
44828
44829
44830 protected $rules = array();
44831
44832
44833
44834
44835 protected $noproxy;
44836
44837
44838
44839
44840 public function __construct($pattern)
44841 {
44842 $this->hostNames = preg_split('{[\s,]+}', $pattern, null, PREG_SPLIT_NO_EMPTY);
44843 $this->noproxy = empty($this->hostNames) || '*' === $this->hostNames[0];
44844 }
44845
44846
44847
44848
44849
44850
44851
44852
44853 public function test($url)
44854 {
44855 if ($this->noproxy) {
44856 return true;
44857 }
44858
44859 if (!$urlData = $this->getUrlData($url)) {
44860 return false;
44861 }
44862
44863 foreach ($this->hostNames as $index => $hostName) {
44864 if ($this->match($index, $hostName, $urlData)) {
44865 return true;
44866 }
44867 }
44868
44869 return false;
44870 }
44871
44872
44873
44874
44875
44876
44877
44878
44879 protected function getUrlData($url)
44880 {
44881 if (!$host = parse_url($url, PHP_URL_HOST)) {
44882 return false;
44883 }
44884
44885 $port = parse_url($url, PHP_URL_PORT);
44886
44887 if (empty($port)) {
44888 switch (parse_url($url, PHP_URL_SCHEME)) {
44889 case 'http':
44890 $port = 80;
44891 break;
44892 case 'https':
44893 $port = 443;
44894 break;
44895 }
44896 }
44897
44898 $hostName = $host . ($port ? ':' . $port : '');
44899 list($host, $port, $err) = $this->splitHostPort($hostName);
44900
44901 if ($err || !$this->ipCheckData($host, $ipdata)) {
44902 return false;
44903 }
44904
44905 return $this->makeData($host, $port, $ipdata);
44906 }
44907
44908
44909
44910
44911
44912
44913
44914
44915
44916
44917 protected function match($index, $hostName, $url)
44918 {
44919 if (!$rule = $this->getRule($index, $hostName)) {
44920
44921 return false;
44922 }
44923
44924 if ($rule->ipdata) {
44925
44926 if (!$url->ipdata) {
44927 return false;
44928 }
44929
44930 if ($rule->ipdata->netmask) {
44931 return $this->matchRange($rule->ipdata, $url->ipdata);
44932 }
44933
44934 $match = $rule->ipdata->ip === $url->ipdata->ip;
44935 } else {
44936
44937 $haystack = substr($url->name, - strlen($rule->name));
44938 $match = stripos($haystack, $rule->name) === 0;
44939 }
44940
44941 if ($match && $rule->port) {
44942 $match = $rule->port === $url->port;
44943 }
44944
44945 return $match;
44946 }
44947
44948
44949
44950
44951
44952
44953
44954
44955
44956 protected function matchRange(stdClass $network, stdClass $target)
44957 {
44958 $net = unpack('C*', $network->ip);
44959 $mask = unpack('C*', $network->netmask);
44960 $ip = unpack('C*', $target->ip);
44961
44962 for ($i = 1; $i < 17; ++$i) {
44963 if (($net[$i] & $mask[$i]) !== ($ip[$i] & $mask[$i])) {
44964 return false;
44965 }
44966 }
44967
44968 return true;
44969 }
44970
44971
44972
44973
44974
44975
44976
44977
44978
44979 private function getRule($index, $hostName)
44980 {
44981 if (array_key_exists($index, $this->rules)) {
44982 return $this->rules[$index];
44983 }
44984
44985 $this->rules[$index] = null;
44986 list($host, $port, $err) = $this->splitHostPort($hostName);
44987
44988 if ($err || !$this->ipCheckData($host, $ipdata, true)) {
44989 return null;
44990 }
44991
44992 $this->rules[$index] = $this->makeData($host, $port, $ipdata);
44993
44994 return $this->rules[$index];
44995 }
44996
44997
44998
44999
45000
45001
45002
45003
45004
45005
45006 private function ipCheckData($host, &$ipdata, $allowPrefix = false)
45007 {
45008 $ipdata = null;
45009 $netmask = null;
45010 $prefix = null;
45011 $modified = false;
45012
45013
45014 if (strpos($host, '/') !== false) {
45015 list($host, $prefix) = explode('/', $host);
45016
45017 if (!$allowPrefix || !$this->validateInt($prefix, 0, 128)) {
45018 return false;
45019 }
45020 $prefix = (int) $prefix;
45021 $modified = true;
45022 }
45023
45024
45025 if (!filter_var($host, FILTER_VALIDATE_IP)) {
45026 return !$modified;
45027 }
45028
45029 list($ip, $size) = $this->ipGetAddr($host);
45030
45031 if ($prefix !== null) {
45032
45033 if ($prefix > $size * 8) {
45034 return false;
45035 }
45036
45037 list($ip, $netmask) = $this->ipGetNetwork($ip, $size, $prefix);
45038 }
45039
45040 $ipdata = $this->makeIpData($ip, $size, $netmask);
45041
45042 return true;
45043 }
45044
45045
45046
45047
45048
45049
45050
45051
45052
45053
45054
45055 private function ipGetAddr($host)
45056 {
45057 $ip = inet_pton($host);
45058 $size = strlen($ip);
45059 $mapped = $this->ipMapTo6($ip, $size);
45060
45061 return array($mapped, $size);
45062 }
45063
45064
45065
45066
45067
45068
45069
45070
45071
45072 private function ipGetMask($prefix, $size)
45073 {
45074 $mask = '';
45075
45076 if ($ones = floor($prefix / 8)) {
45077 $mask = str_repeat(chr(255), $ones);
45078 }
45079
45080 if ($remainder = $prefix % 8) {
45081 $mask .= chr(0xff ^ (0xff >> $remainder));
45082 }
45083
45084 $mask = str_pad($mask, $size, chr(0));
45085
45086 return $this->ipMapTo6($mask, $size);
45087 }
45088
45089
45090
45091
45092
45093
45094
45095
45096
45097
45098 private function ipGetNetwork($rangeIp, $size, $prefix)
45099 {
45100 $netmask = $this->ipGetMask($prefix, $size);
45101
45102
45103 $mask = unpack('C*', $netmask);
45104 $ip = unpack('C*', $rangeIp);
45105 $net = '';
45106
45107 for ($i = 1; $i < 17; ++$i) {
45108 $net .= chr($ip[$i] & $mask[$i]);
45109 }
45110
45111 return array($net, $netmask);
45112 }
45113
45114
45115
45116
45117
45118
45119
45120
45121
45122 private function ipMapTo6($binary, $size)
45123 {
45124 if ($size === 4) {
45125 $prefix = str_repeat(chr(0), 10) . str_repeat(chr(255), 2);
45126 $binary = $prefix . $binary;
45127 }
45128
45129 return $binary;
45130 }
45131
45132
45133
45134
45135
45136
45137
45138
45139
45140
45141 private function makeData($host, $port, $ipdata)
45142 {
45143 return (object) array(
45144 'host' => $host,
45145 'name' => '.' . ltrim($host, '.'),
45146 'port' => $port,
45147 'ipdata' => $ipdata,
45148 );
45149 }
45150
45151
45152
45153
45154
45155
45156
45157
45158
45159
45160 private function makeIpData($ip, $size, $netmask)
45161 {
45162 return (object) array(
45163 'ip' => $ip,
45164 'size' => $size,
45165 'netmask' => $netmask,
45166 );
45167 }
45168
45169
45170
45171
45172
45173
45174
45175
45176 private function splitHostPort($hostName)
45177 {
45178
45179 $error = array('', '', true);
45180 $port = 0;
45181 $ip6 = '';
45182
45183
45184 if ($hostName[0] === '[') {
45185 $index = strpos($hostName, ']');
45186
45187
45188 if (false === $index || $index < 3) {
45189 return $error;
45190 }
45191
45192 $ip6 = substr($hostName, 1, $index - 1);
45193 $hostName = substr($hostName, $index + 1);
45194
45195 if (strpbrk($hostName, '[]') !== false
45196 || substr_count($hostName, ':') > 1) {
45197 return $error;
45198 }
45199 }
45200
45201 if (substr_count($hostName, ':') === 1) {
45202 $index = strpos($hostName, ':');
45203 $port = substr($hostName, $index + 1);
45204 $hostName = substr($hostName, 0, $index);
45205
45206 if (!$this->validateInt($port, 1, 65535)) {
45207 return $error;
45208 }
45209
45210 $port = (int) $port;
45211 }
45212
45213 $host = $ip6 . $hostName;
45214
45215 return array($host, $port, false);
45216 }
45217
45218
45219
45220
45221
45222
45223
45224
45225 private function validateInt($int, $min, $max)
45226 {
45227 $options = array(
45228 'options' => array(
45229 'min_range' => $min,
45230 'max_range' => $max)
45231 );
45232
45233 return false !== filter_var($int, FILTER_VALIDATE_INT, $options);
45234 }
45235 }
45236 <?php
45237
45238
45239 namespace Composer\Util;
45240
45241 use Composer\Package\Link;
45242 use Composer\Package\PackageInterface;
45243
45244 class PackageSorter
45245 {
45246
45247
45248
45249
45250
45251
45252
45253
45254 public static function sortPackages(array $packages) {
45255 $usageList = array();
45256
45257 foreach ($packages as $package) { 
45258 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { 
45259 $target = $link->getTarget();
45260 $usageList[$target][] = $package->getName();
45261 }
45262 }
45263 $computing = array();
45264 $computed = array();
45265 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
45266
45267 if (isset($computed[$name])) {
45268 return $computed[$name];
45269 }
45270
45271
45272 if (isset($computing[$name])) {
45273 return 0;
45274 }
45275
45276 $computing[$name] = true;
45277 $weight = 0;
45278
45279 if (isset($usageList[$name])) {
45280 foreach ($usageList[$name] as $user) {
45281 $weight -= 1 - $computeImportance($user);
45282 }
45283 }
45284
45285 unset($computing[$name]);
45286 $computed[$name] = $weight;
45287
45288 return $weight;
45289 };
45290
45291 $weightList = array();
45292
45293 foreach ($packages as $name => $package) {
45294 $weight = $computeImportance($name);
45295 $weightList[$name] = $weight;
45296 }
45297
45298 $stable_sort = function (&$array) {
45299 static $transform, $restore;
45300
45301 $i = 0;
45302
45303 if (!$transform) {
45304 $transform = function (&$v, $k) use (&$i) {
45305 $v = array($v, ++$i, $k, $v);
45306 };
45307
45308 $restore = function (&$v) {
45309 $v = $v[3];
45310 };
45311 }
45312
45313 array_walk($array, $transform);
45314 asort($array);
45315 array_walk($array, $restore);
45316 };
45317
45318 $stable_sort($weightList);
45319
45320 $sortedPackages = array();
45321
45322 foreach (array_keys($weightList) as $name) {
45323 $sortedPackages[] = $packages[$name];
45324 }
45325 return $sortedPackages;
45326 }
45327 }
45328 <?php
45329
45330
45331
45332
45333
45334
45335
45336
45337
45338
45339
45340 namespace Composer\Util;
45341
45342 use Composer\IO\IOInterface;
45343 use Symfony\Component\Process\Process;
45344
45345
45346
45347
45348 class Perforce
45349 {
45350 protected $path;
45351 protected $p4Depot;
45352 protected $p4Client;
45353 protected $p4User;
45354 protected $p4Password;
45355 protected $p4Port;
45356 protected $p4Stream;
45357 protected $p4ClientSpec;
45358 protected $p4DepotType;
45359 protected $p4Branch;
45360 protected $process;
45361 protected $uniquePerforceClientName;
45362 protected $windowsFlag;
45363 protected $commandResult;
45364
45365 protected $io;
45366
45367 protected $filesystem;
45368
45369 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
45370 {
45371 $this->windowsFlag = $isWindows;
45372 $this->p4Port = $port;
45373 $this->initializePath($path);
45374 $this->process = $process;
45375 $this->initialize($repoConfig);
45376 $this->io = $io;
45377 }
45378
45379 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
45380 {
45381 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
45382 }
45383
45384 public static function checkServerExists($url, ProcessExecutor $processExecutor)
45385 {
45386 $output = null;
45387
45388 return 0 === $processExecutor->execute('p4 -p ' . ProcessExecutor::escape($url) . ' info -s', $output);
45389 }
45390
45391 public function initialize($repoConfig)
45392 {
45393 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
45394 if (!$repoConfig) {
45395 return;
45396 }
45397 if (isset($repoConfig['unique_perforce_client_name'])) {
45398 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
45399 }
45400
45401 if (isset($repoConfig['depot'])) {
45402 $this->p4Depot = $repoConfig['depot'];
45403 }
45404 if (isset($repoConfig['branch'])) {
45405 $this->p4Branch = $repoConfig['branch'];
45406 }
45407 if (isset($repoConfig['p4user'])) {
45408 $this->p4User = $repoConfig['p4user'];
45409 } else {
45410 $this->p4User = $this->getP4variable('P4USER');
45411 }
45412 if (isset($repoConfig['p4password'])) {
45413 $this->p4Password = $repoConfig['p4password'];
45414 }
45415 }
45416
45417 public function initializeDepotAndBranch($depot, $branch)
45418 {
45419 if (isset($depot)) {
45420 $this->p4Depot = $depot;
45421 }
45422 if (isset($branch)) {
45423 $this->p4Branch = $branch;
45424 }
45425 }
45426
45427 public function generateUniquePerforceClientName()
45428 {
45429 return gethostname() . "_" . time();
45430 }
45431
45432 public function cleanupClientSpec()
45433 {
45434 $client = $this->getClient();
45435 $task = 'client -d ' . ProcessExecutor::escape($client);
45436 $useP4Client = false;
45437 $command = $this->generateP4Command($task, $useP4Client);
45438 $this->executeCommand($command);
45439 $clientSpec = $this->getP4ClientSpec();
45440 $fileSystem = $this->getFilesystem();
45441 $fileSystem->remove($clientSpec);
45442 }
45443
45444 protected function executeCommand($command)
45445 {
45446 $this->commandResult = '';
45447
45448 return $this->process->execute($command, $this->commandResult);
45449 }
45450
45451 public function getClient()
45452 {
45453 if (!isset($this->p4Client)) {
45454 $cleanStreamName = str_replace(array('//', '/', '@'), array('', '_', ''), $this->getStream());
45455 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
45456 }
45457
45458 return $this->p4Client;
45459 }
45460
45461 protected function getPath()
45462 {
45463 return $this->path;
45464 }
45465
45466 public function initializePath($path)
45467 {
45468 $this->path = $path;
45469 $fs = $this->getFilesystem();
45470 $fs->ensureDirectoryExists($path);
45471 }
45472
45473 protected function getPort()
45474 {
45475 return $this->p4Port;
45476 }
45477
45478 public function setStream($stream)
45479 {
45480 $this->p4Stream = $stream;
45481 $index = strrpos($stream, '/');
45482
45483 if ($index > 2) {
45484 $this->p4DepotType = 'stream';
45485 }
45486 }
45487
45488 public function isStream()
45489 {
45490 return (strcmp($this->p4DepotType, 'stream') === 0);
45491 }
45492
45493 public function getStream()
45494 {
45495 if (!isset($this->p4Stream)) {
45496 if ($this->isStream()) {
45497 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
45498 } else {
45499 $this->p4Stream = '//' . $this->p4Depot;
45500 }
45501 }
45502
45503 return $this->p4Stream;
45504 }
45505
45506 public function getStreamWithoutLabel($stream)
45507 {
45508 $index = strpos($stream, '@');
45509 if ($index === false) {
45510 return $stream;
45511 }
45512
45513 return substr($stream, 0, $index);
45514 }
45515
45516 public function getP4ClientSpec()
45517 {
45518 return $this->path . '/' . $this->getClient() . '.p4.spec';
45519 }
45520
45521 public function getUser()
45522 {
45523 return $this->p4User;
45524 }
45525
45526 public function setUser($user)
45527 {
45528 $this->p4User = $user;
45529 }
45530
45531 public function queryP4User()
45532 {
45533 $this->getUser();
45534 if (strlen($this->p4User) > 0) {
45535 return;
45536 }
45537 $this->p4User = $this->getP4variable('P4USER');
45538 if (strlen($this->p4User) > 0) {
45539 return;
45540 }
45541 $this->p4User = $this->io->ask('Enter P4 User:');
45542 if ($this->windowsFlag) {
45543 $command = 'p4 set P4USER=' . $this->p4User;
45544 } else {
45545 $command = 'export P4USER=' . $this->p4User;
45546 }
45547 $this->executeCommand($command);
45548 }
45549
45550 protected function getP4variable($name)
45551 {
45552 if ($this->windowsFlag) {
45553 $command = 'p4 set';
45554 $this->executeCommand($command);
45555 $result = trim($this->commandResult);
45556 $resArray = explode(PHP_EOL, $result);
45557 foreach ($resArray as $line) {
45558 $fields = explode('=', $line);
45559 if (strcmp($name, $fields[0]) == 0) {
45560 $index = strpos($fields[1], ' ');
45561 if ($index === false) {
45562 $value = $fields[1];
45563 } else {
45564 $value = substr($fields[1], 0, $index);
45565 }
45566 $value = trim($value);
45567
45568 return $value;
45569 }
45570 }
45571
45572 return null;
45573 }
45574
45575 $command = 'echo $' . $name;
45576 $this->executeCommand($command);
45577 $result = trim($this->commandResult);
45578
45579 return $result;
45580 }
45581
45582 public function queryP4Password()
45583 {
45584 if (isset($this->p4Password)) {
45585 return $this->p4Password;
45586 }
45587 $password = $this->getP4variable('P4PASSWD');
45588 if (strlen($password) <= 0) {
45589 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
45590 }
45591 $this->p4Password = $password;
45592
45593 return $password;
45594 }
45595
45596 public function generateP4Command($command, $useClient = true)
45597 {
45598 $p4Command = 'p4 ';
45599 $p4Command .= '-u ' . $this->getUser() . ' ';
45600 if ($useClient) {
45601 $p4Command .= '-c ' . $this->getClient() . ' ';
45602 }
45603 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ' . $command;
45604
45605 return $p4Command;
45606 }
45607
45608 public function isLoggedIn()
45609 {
45610 $command = $this->generateP4Command('login -s', false);
45611 $exitCode = $this->executeCommand($command);
45612 if ($exitCode) {
45613 $errorOutput = $this->process->getErrorOutput();
45614 $index = strpos($errorOutput, $this->getUser());
45615 if ($index === false) {
45616 $index = strpos($errorOutput, 'p4');
45617 if ($index === false) {
45618 return false;
45619 }
45620 throw new \Exception('p4 command not found in path: ' . $errorOutput);
45621 }
45622 throw new \Exception('Invalid user name: ' . $this->getUser());
45623 }
45624
45625 return true;
45626 }
45627
45628 public function connectClient()
45629 {
45630 $p4CreateClientCommand = $this->generateP4Command(
45631 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
45632 );
45633 $this->executeCommand($p4CreateClientCommand);
45634 }
45635
45636 public function syncCodeBase($sourceReference)
45637 {
45638 $prevDir = getcwd();
45639 chdir($this->path);
45640 $p4SyncCommand = $this->generateP4Command('sync -f ');
45641 if (null !== $sourceReference) {
45642 $p4SyncCommand .= '@' . $sourceReference;
45643 }
45644 $this->executeCommand($p4SyncCommand);
45645 chdir($prevDir);
45646 }
45647
45648 public function writeClientSpecToFile($spec)
45649 {
45650 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
45651 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
45652 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
45653 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
45654 fwrite($spec, 'Description:' . PHP_EOL);
45655 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
45656 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
45657 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
45658 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
45659 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
45660 if ($this->isStream()) {
45661 fwrite($spec, 'Stream:' . PHP_EOL);
45662 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
45663 } else {
45664 fwrite(
45665 $spec,
45666 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
45667 );
45668 }
45669 }
45670
45671 public function writeP4ClientSpec()
45672 {
45673 $clientSpec = $this->getP4ClientSpec();
45674 $spec = fopen($clientSpec, 'w');
45675 try {
45676 $this->writeClientSpecToFile($spec);
45677 } catch (\Exception $e) {
45678 fclose($spec);
45679 throw $e;
45680 }
45681 fclose($spec);
45682 }
45683
45684 protected function read($pipe, $name)
45685 {
45686 if (feof($pipe)) {
45687 return;
45688 }
45689 $line = fgets($pipe);
45690 while ($line !== false) {
45691 $line = fgets($pipe);
45692 }
45693 }
45694
45695 public function windowsLogin($password)
45696 {
45697 $command = $this->generateP4Command(' login -a');
45698
45699
45700 if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
45701 $process = Process::fromShellCommandline($command, null, null, $password);
45702 } else {
45703 $process = new Process($command, null, null, $password);
45704 }
45705
45706 return $process->run();
45707 }
45708
45709 public function p4Login()
45710 {
45711 $this->queryP4User();
45712 if (!$this->isLoggedIn()) {
45713 $password = $this->queryP4Password();
45714 if ($this->windowsFlag) {
45715 $this->windowsLogin($password);
45716 } else {
45717 $command = 'echo ' . ProcessExecutor::escape($password) . ' | ' . $this->generateP4Command(' login -a', false);
45718 $exitCode = $this->executeCommand($command);
45719 $result = trim($this->commandResult);
45720 if ($exitCode) {
45721 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
45722 }
45723 }
45724 }
45725 }
45726
45727 public function getComposerInformation($identifier)
45728 {
45729 $composerFileContent = $this->getFileContent('composer.json', $identifier);
45730
45731 if (!$composerFileContent) {
45732 return;
45733 }
45734
45735 return json_decode($composerFileContent, true);
45736 }
45737
45738 public function getFileContent($file, $identifier)
45739 {
45740 $path = $this->getFilePath($file, $identifier);
45741
45742 $command = $this->generateP4Command(' print ' . ProcessExecutor::escape($path));
45743 $this->executeCommand($command);
45744 $result = $this->commandResult;
45745
45746 if (!trim($result)) {
45747 return null;
45748 }
45749
45750 return $result;
45751 }
45752
45753 public function getFilePath($file, $identifier)
45754 {
45755 $index = strpos($identifier, '@');
45756 if ($index === false) {
45757 $path = $identifier. '/' . $file;
45758
45759 return $path;
45760 }
45761
45762 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
45763 $command = $this->generateP4Command(' files ' . ProcessExecutor::escape($path), false);
45764 $this->executeCommand($command);
45765 $result = $this->commandResult;
45766 $index2 = strpos($result, 'no such file(s).');
45767 if ($index2 === false) {
45768 $index3 = strpos($result, 'change');
45769 if ($index3 !== false) {
45770 $phrase = trim(substr($result, $index3));
45771 $fields = explode(' ', $phrase);
45772
45773 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
45774 }
45775 }
45776
45777 return null;
45778 }
45779
45780 public function getBranches()
45781 {
45782 $possibleBranches = array();
45783 if (!$this->isStream()) {
45784 $possibleBranches[$this->p4Branch] = $this->getStream();
45785 } else {
45786 $command = $this->generateP4Command('streams '.ProcessExecutor::escape('//' . $this->p4Depot . '/...'));
45787 $this->executeCommand($command);
45788 $result = $this->commandResult;
45789 $resArray = explode(PHP_EOL, $result);
45790 foreach ($resArray as $line) {
45791 $resBits = explode(' ', $line);
45792 if (count($resBits) > 4) {
45793 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
45794 $possibleBranches[$branch] = $resBits[1];
45795 }
45796 }
45797 }
45798 $command = $this->generateP4Command('changes '. ProcessExecutor::escape($this->getStream() . '/...'), false);
45799 $this->executeCommand($command);
45800 $result = $this->commandResult;
45801 $resArray = explode(PHP_EOL, $result);
45802 $lastCommit = $resArray[0];
45803 $lastCommitArr = explode(' ', $lastCommit);
45804 $lastCommitNum = $lastCommitArr[1];
45805
45806 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
45807
45808 return $branches;
45809 }
45810
45811 public function getTags()
45812 {
45813 $command = $this->generateP4Command('labels');
45814 $this->executeCommand($command);
45815 $result = $this->commandResult;
45816 $resArray = explode(PHP_EOL, $result);
45817 $tags = array();
45818 foreach ($resArray as $line) {
45819 if (strpos($line, 'Label') !== false) {
45820 $fields = explode(' ', $line);
45821 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
45822 }
45823 }
45824
45825 return $tags;
45826 }
45827
45828 public function checkStream()
45829 {
45830 $command = $this->generateP4Command('depots', false);
45831 $this->executeCommand($command);
45832 $result = $this->commandResult;
45833 $resArray = explode(PHP_EOL, $result);
45834 foreach ($resArray as $line) {
45835 if (strpos($line, 'Depot') !== false) {
45836 $fields = explode(' ', $line);
45837 if (strcmp($this->p4Depot, $fields[1]) === 0) {
45838 $this->p4DepotType = $fields[3];
45839
45840 return $this->isStream();
45841 }
45842 }
45843 }
45844
45845 return false;
45846 }
45847
45848
45849
45850
45851
45852 protected function getChangeList($reference)
45853 {
45854 $index = strpos($reference, '@');
45855 if ($index === false) {
45856 return null;
45857 }
45858 $label = substr($reference, $index);
45859 $command = $this->generateP4Command(' changes -m1 ' . ProcessExecutor::escape($label));
45860 $this->executeCommand($command);
45861 $changes = $this->commandResult;
45862 if (strpos($changes, 'Change') !== 0) {
45863 return null;
45864 }
45865 $fields = explode(' ', $changes);
45866
45867 return $fields[1];
45868 }
45869
45870
45871
45872
45873
45874
45875 public function getCommitLogs($fromReference, $toReference)
45876 {
45877 $fromChangeList = $this->getChangeList($fromReference);
45878 if ($fromChangeList === null) {
45879 return null;
45880 }
45881 $toChangeList = $this->getChangeList($toReference);
45882 if ($toChangeList === null) {
45883 return null;
45884 }
45885 $index = strpos($fromReference, '@');
45886 $main = substr($fromReference, 0, $index) . '/...';
45887 $command = $this->generateP4Command('filelog ' . ProcessExecutor::escape($main . '@' . $fromChangeList. ',' . $toChangeList));
45888 $this->executeCommand($command);
45889
45890 return $this->commandResult;
45891 }
45892
45893 public function getFilesystem()
45894 {
45895 if (empty($this->filesystem)) {
45896 $this->filesystem = new Filesystem($this->process);
45897 }
45898
45899 return $this->filesystem;
45900 }
45901
45902 public function setFilesystem(Filesystem $fs)
45903 {
45904 $this->filesystem = $fs;
45905 }
45906 }
45907 <?php
45908
45909
45910
45911
45912
45913
45914
45915
45916
45917
45918
45919 namespace Composer\Util;
45920
45921
45922
45923
45924
45925
45926 class Platform
45927 {
45928
45929
45930
45931
45932
45933
45934 public static function expandPath($path)
45935 {
45936 if (preg_match('#^~[\\/]#', $path)) {
45937 return self::getUserDirectory() . substr($path, 1);
45938 }
45939
45940 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
45941
45942 if (Platform::isWindows() && $matches['var'] == 'HOME') {
45943 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
45944 }
45945
45946 return getenv($matches['var']) . $matches['path'];
45947 }, $path);
45948 }
45949
45950
45951
45952
45953
45954 public static function getUserDirectory()
45955 {
45956 if (false !== ($home = getenv('HOME'))) {
45957 return $home;
45958 }
45959
45960 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
45961 return $home;
45962 }
45963
45964 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
45965 $info = posix_getpwuid(posix_getuid());
45966
45967 return $info['dir'];
45968 }
45969
45970 throw new \RuntimeException('Could not determine user directory');
45971 }
45972
45973
45974
45975
45976 public static function isWindows()
45977 {
45978 return defined('PHP_WINDOWS_VERSION_BUILD');
45979 }
45980
45981
45982
45983
45984
45985 public static function strlen($str)
45986 {
45987 static $useMbString = null;
45988 if (null === $useMbString) {
45989 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
45990 }
45991
45992 if ($useMbString) {
45993 return mb_strlen($str, '8bit');
45994 }
45995
45996 return strlen($str);
45997 }
45998 }
45999 <?php
46000
46001
46002
46003
46004
46005
46006
46007
46008
46009
46010
46011 namespace Composer\Util;
46012
46013 use Composer\IO\IOInterface;
46014 use Composer\Util\Platform;
46015 use Symfony\Component\Process\Process;
46016 use Symfony\Component\Process\ProcessUtils;
46017
46018
46019
46020
46021 class ProcessExecutor
46022 {
46023 protected static $timeout = 300;
46024
46025 protected $captureOutput;
46026 protected $errorOutput;
46027 protected $io;
46028
46029 public function __construct(IOInterface $io = null)
46030 {
46031 $this->io = $io;
46032 }
46033
46034
46035
46036
46037
46038
46039
46040
46041
46042
46043 public function execute($command, &$output = null, $cwd = null)
46044 {
46045 if ($this->io && $this->io->isDebug()) {
46046 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
46047
46048 if (preg_match('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) {
46049 return '://***:***@';
46050 }
46051
46052 return '://'.$m['user'].':***@';
46053 }, $command);
46054 $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand);
46055 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
46056 }
46057
46058
46059
46060 if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
46061 $cwd = realpath(getcwd());
46062 }
46063
46064 if (null !== $cwd && !is_dir($cwd)) {
46065 throw new \RuntimeException('The given CWD for the process does not exist: '.$cwd);
46066 }
46067
46068 $this->captureOutput = func_num_args() > 1;
46069 $this->errorOutput = null;
46070
46071
46072 if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
46073 $process = Process::fromShellCommandline($command, $cwd, null, null, static::getTimeout());
46074 } else {
46075 $process = new Process($command, $cwd, null, null, static::getTimeout());
46076 }
46077
46078 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
46079 $process->run($callback);
46080
46081 if ($this->captureOutput && !is_callable($output)) {
46082 $output = $process->getOutput();
46083 }
46084
46085 $this->errorOutput = $process->getErrorOutput();
46086
46087 return $process->getExitCode();
46088 }
46089
46090 public function splitLines($output)
46091 {
46092 $output = trim($output);
46093
46094 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
46095 }
46096
46097
46098
46099
46100
46101
46102 public function getErrorOutput()
46103 {
46104 return $this->errorOutput;
46105 }
46106
46107 public function outputHandler($type, $buffer)
46108 {
46109 if ($this->captureOutput) {
46110 return;
46111 }
46112
46113 if (null === $this->io) {
46114 echo $buffer;
46115
46116 return;
46117 }
46118
46119 if (method_exists($this->io, 'writeRaw')) {
46120 if (Process::ERR === $type) {
46121 $this->io->writeErrorRaw($buffer, false);
46122 } else {
46123 $this->io->writeRaw($buffer, false);
46124 }
46125 } else {
46126 if (Process::ERR === $type) {
46127 $this->io->writeError($buffer, false);
46128 } else {
46129 $this->io->write($buffer, false);
46130 }
46131 }
46132 }
46133
46134 public static function getTimeout()
46135 {
46136 return static::$timeout;
46137 }
46138
46139 public static function setTimeout($timeout)
46140 {
46141 static::$timeout = $timeout;
46142 }
46143
46144
46145
46146
46147
46148
46149
46150
46151 public static function escape($argument)
46152 {
46153 return self::escapeArgument($argument);
46154 }
46155
46156
46157
46158
46159
46160
46161
46162
46163
46164
46165
46166
46167
46168
46169
46170
46171 private static function escapeArgument($argument)
46172 {
46173 if ('' === ($argument = (string) $argument)) {
46174 return escapeshellarg($argument);
46175 }
46176
46177 if (!Platform::isWindows()) {
46178 return "'".str_replace("'", "'\\''", $argument)."'";
46179 }
46180
46181
46182 $argument = strtr($argument, "\n", ' ');
46183
46184 $quote = strpbrk($argument, " \t") !== false;
46185 $argument = preg_replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes);
46186 $meta = $dquotes || preg_match('/%[^%]+%|![^!]+!/', $argument);
46187
46188 if (!$meta && !$quote) {
46189 $quote = strpbrk($argument, '^&|<>()') !== false;
46190 }
46191
46192 if ($quote) {
46193 $argument = '"'.preg_replace('/(\\\\*)$/', '$1$1', $argument).'"';
46194 }
46195
46196 if ($meta) {
46197 $argument = preg_replace('/(["^&|<>()%])/', '^$1', $argument);
46198 $argument = preg_replace('/(!)/', '^^$1', $argument);
46199 }
46200
46201 return $argument;
46202 }
46203 }
46204 <?php
46205
46206
46207
46208
46209
46210
46211
46212
46213
46214
46215
46216 namespace Composer\Util;
46217
46218 use Composer\Config;
46219 use Composer\Composer;
46220 use Composer\Semver\Constraint\Constraint;
46221 use Composer\Package\Version\VersionParser;
46222 use Composer\IO\IOInterface;
46223 use Composer\Downloader\TransportException;
46224 use Composer\CaBundle\CaBundle;
46225 use Psr\Log\LoggerInterface;
46226
46227
46228
46229
46230
46231
46232 class RemoteFilesystem
46233 {
46234 private $io;
46235 private $config;
46236 private $scheme;
46237 private $bytesMax;
46238 private $originUrl;
46239 private $fileUrl;
46240 private $fileName;
46241 private $retry;
46242 private $progress;
46243 private $lastProgress;
46244 private $options = array();
46245 private $peerCertificateMap = array();
46246 private $disableTls = false;
46247 private $retryAuthFailure;
46248 private $lastHeaders;
46249 private $storeAuth;
46250 private $degradedMode = false;
46251 private $redirects;
46252 private $maxRedirects = 20;
46253 private $displayedOriginAuthentications = array();
46254
46255
46256
46257
46258
46259
46260
46261
46262
46263 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
46264 {
46265 $this->io = $io;
46266
46267
46268
46269 if ($disableTls === false) {
46270 $this->options = $this->getTlsDefaults($options);
46271 } else {
46272 $this->disableTls = true;
46273 }
46274
46275
46276 $this->options = array_replace_recursive($this->options, $options);
46277 $this->config = $config;
46278 }
46279
46280
46281
46282
46283
46284
46285
46286
46287
46288
46289
46290
46291 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
46292 {
46293 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
46294 }
46295
46296
46297
46298
46299
46300
46301
46302
46303
46304
46305
46306 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
46307 {
46308 return $this->get($originUrl, $fileUrl, $options, null, $progress);
46309 }
46310
46311
46312
46313
46314
46315
46316 public function getOptions()
46317 {
46318 return $this->options;
46319 }
46320
46321
46322
46323
46324
46325
46326 public function setOptions(array $options)
46327 {
46328 $this->options = array_replace_recursive($this->options, $options);
46329 }
46330
46331
46332
46333
46334
46335
46336 public function isTlsDisabled()
46337 {
46338 return $this->disableTls === true;
46339 }
46340
46341
46342
46343
46344
46345
46346 public function getLastHeaders()
46347 {
46348 return $this->lastHeaders;
46349 }
46350
46351
46352
46353
46354
46355
46356 public function findHeaderValue(array $headers, $name)
46357 {
46358 $value = null;
46359 foreach ($headers as $header) {
46360 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
46361 $value = $match[1];
46362 } elseif (preg_match('{^HTTP/}i', $header)) {
46363
46364
46365 $value = null;
46366 }
46367 }
46368
46369 return $value;
46370 }
46371
46372
46373
46374
46375
46376 public function findStatusCode(array $headers)
46377 {
46378 $value = null;
46379 foreach ($headers as $header) {
46380 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
46381
46382
46383 $value = (int) $match[1];
46384 }
46385 }
46386
46387 return $value;
46388 }
46389
46390
46391
46392
46393
46394 public function findStatusMessage(array $headers)
46395 {
46396 $value = null;
46397 foreach ($headers as $header) {
46398 if (preg_match('{^HTTP/\S+ \d+}i', $header)) {
46399
46400
46401 $value = $header;
46402 }
46403 }
46404
46405 return $value;
46406 }
46407
46408
46409
46410
46411
46412
46413
46414
46415
46416
46417
46418
46419
46420
46421
46422 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
46423 {
46424 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
46425 $originUrl = 'github.com';
46426 }
46427
46428
46429
46430 if (
46431 $this->config
46432 && is_array($this->config->get('gitlab-domains'))
46433 && false === strpos($originUrl, '/')
46434 && !in_array($originUrl, $this->config->get('gitlab-domains'))
46435 ) {
46436 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
46437 if (0 === strpos($gitlabDomain, $originUrl)) {
46438 $originUrl = $gitlabDomain;
46439 break;
46440 }
46441 }
46442 unset($gitlabDomain);
46443 }
46444
46445 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
46446 $this->bytesMax = 0;
46447 $this->originUrl = $originUrl;
46448 $this->fileUrl = $fileUrl;
46449 $this->fileName = $fileName;
46450 $this->progress = $progress;
46451 $this->lastProgress = null;
46452 $this->retryAuthFailure = true;
46453 $this->lastHeaders = array();
46454 $this->redirects = 1; 
46455
46456
46457 if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
46458 $this->io->setAuthentication($originUrl, rawurldecode($match[1]), rawurldecode($match[2]));
46459 }
46460
46461 $tempAdditionalOptions = $additionalOptions;
46462 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
46463 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
46464
46465 unset($tempAdditionalOptions['retry-auth-failure']);
46466 }
46467
46468 $isRedirect = false;
46469 if (isset($tempAdditionalOptions['redirects'])) {
46470 $this->redirects = $tempAdditionalOptions['redirects'];
46471 $isRedirect = true;
46472
46473 unset($tempAdditionalOptions['redirects']);
46474 }
46475
46476 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
46477 unset($tempAdditionalOptions);
46478
46479 $origFileUrl = $fileUrl;
46480
46481 if (isset($options['github-token'])) {
46482
46483 if (preg_match('{^https?://api\.github\.com/}', $fileUrl)) {
46484 $options['http']['header'][] = 'Authorization: token '.$options['github-token'];
46485 }
46486 unset($options['github-token']);
46487 }
46488
46489 if (isset($options['gitlab-token'])) {
46490 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
46491 unset($options['gitlab-token']);
46492 }
46493
46494 if (isset($options['http'])) {
46495 $options['http']['ignore_errors'] = true;
46496 }
46497
46498 if ($this->degradedMode && substr($fileUrl, 0, 26) === 'http://repo.packagist.org/') {
46499
46500 $fileUrl = 'http://' . gethostbyname('repo.packagist.org') . substr($fileUrl, 20);
46501 $degradedPackagist = true;
46502 }
46503
46504 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
46505
46506 $actualContextOptions = stream_context_get_options($ctx);
46507 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
46508 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $this->stripCredentialsFromUrl($origFileUrl) . $usingProxy, true, IOInterface::DEBUG);
46509 unset($origFileUrl, $actualContextOptions);
46510
46511
46512 if ((!preg_match('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
46513 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
46514 }
46515
46516 if ($this->progress && !$isRedirect) {
46517 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
46518 }
46519
46520 $errorMessage = '';
46521 $errorCode = 0;
46522 $result = false;
46523 set_error_handler(function ($code, $msg) use (&$errorMessage) {
46524 if ($errorMessage) {
46525 $errorMessage .= "\n";
46526 }
46527 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
46528
46529 return true;
46530 });
46531 try {
46532 $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header);
46533
46534 if (!empty($http_response_header[0])) {
46535 $statusCode = $this->findStatusCode($http_response_header);
46536 if ($statusCode >= 400 && $this->findHeaderValue($http_response_header, 'content-type') === 'application/json') {
46537 self::outputWarnings($this->io, $originUrl, json_decode($result, true));
46538 }
46539
46540 if (in_array($statusCode, array(401, 403)) && $this->retryAuthFailure) {
46541 $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), null, $http_response_header);
46542 }
46543 }
46544
46545 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
46546 if ($contentLength && Platform::strlen($result) < $contentLength) {
46547
46548 $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
46549 $e->setHeaders($http_response_header);
46550 $e->setStatusCode($this->findStatusCode($http_response_header));
46551 $e->setResponse($result);
46552 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
46553
46554 throw $e;
46555 }
46556
46557 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
46558
46559 $params = stream_context_get_params($ctx);
46560 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
46561 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
46562
46563
46564 if ($expectedPeerFingerprint !== $peerFingerprint) {
46565 throw new TransportException('Peer fingerprint did not match');
46566 }
46567 }
46568 } catch (\Exception $e) {
46569 if ($e instanceof TransportException && !empty($http_response_header[0])) {
46570 $e->setHeaders($http_response_header);
46571 $e->setStatusCode($this->findStatusCode($http_response_header));
46572 }
46573 if ($e instanceof TransportException && $result !== false) {
46574 $e->setResponse($result);
46575 }
46576 $result = false;
46577 }
46578 if ($errorMessage && !filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
46579 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
46580 }
46581 restore_error_handler();
46582 if (isset($e) && !$this->retry) {
46583 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
46584 $this->degradedMode = true;
46585 $this->io->writeError('');
46586 $this->io->writeError(array(
46587 '<error>'.$e->getMessage().'</error>',
46588 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
46589 ));
46590
46591 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46592 }
46593
46594 throw $e;
46595 }
46596
46597 $statusCode = null;
46598 $contentType = null;
46599 $locationHeader = null;
46600 if (!empty($http_response_header[0])) {
46601 $statusCode = $this->findStatusCode($http_response_header);
46602 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
46603 $locationHeader = $this->findHeaderValue($http_response_header, 'location');
46604 }
46605
46606
46607 if ($originUrl === 'bitbucket.org'
46608 && !$this->isPublicBitBucketDownload($fileUrl)
46609 && substr($fileUrl, -4) === '.zip'
46610 && (!$locationHeader || substr(parse_url($locationHeader, PHP_URL_PATH), -4) !== '.zip')
46611 && $contentType && preg_match('{^text/html\b}i', $contentType)
46612 ) {
46613 $result = false;
46614 if ($this->retryAuthFailure) {
46615 $this->promptAuthAndRetry(401);
46616 }
46617 }
46618
46619
46620 if ($statusCode === 404
46621 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
46622 && false !== strpos($fileUrl, 'archive.zip')
46623 ) {
46624 $result = false;
46625 if ($this->retryAuthFailure) {
46626 $this->promptAuthAndRetry(401);
46627 }
46628 }
46629
46630
46631 $hasFollowedRedirect = false;
46632 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
46633 $hasFollowedRedirect = true;
46634 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
46635 }
46636
46637
46638 if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
46639 if (!$this->retry) {
46640 if ($this->progress && !$this->retry && !$isRedirect) {
46641 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
46642 }
46643
46644 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
46645 $e->setHeaders($http_response_header);
46646 $e->setResponse($result);
46647 $e->setStatusCode($statusCode);
46648 throw $e;
46649 }
46650 $result = false;
46651 }
46652
46653 if ($this->progress && !$this->retry && !$isRedirect) {
46654 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
46655 }
46656
46657
46658 if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
46659 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
46660 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
46661
46662 if ($decode) {
46663 try {
46664 if (PHP_VERSION_ID >= 50400) {
46665 $result = zlib_decode($result);
46666 } else {
46667
46668 $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
46669 }
46670
46671 if (!$result) {
46672 throw new TransportException('Failed to decode zlib stream');
46673 }
46674 } catch (\Exception $e) {
46675 if ($this->degradedMode) {
46676 throw $e;
46677 }
46678
46679 $this->degradedMode = true;
46680 $this->io->writeError(array(
46681 '',
46682 '<error>Failed to decode response: '.$e->getMessage().'</error>',
46683 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
46684 ));
46685
46686 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46687 }
46688 }
46689 }
46690
46691
46692 if (false !== $result && null !== $fileName && !$isRedirect) {
46693 if ('' === $result) {
46694 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
46695 }
46696
46697 $errorMessage = '';
46698 set_error_handler(function ($code, $msg) use (&$errorMessage) {
46699 if ($errorMessage) {
46700 $errorMessage .= "\n";
46701 }
46702 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
46703
46704 return true;
46705 });
46706 $result = (bool) file_put_contents($fileName, $result);
46707 restore_error_handler();
46708 if (false === $result) {
46709 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
46710 }
46711 }
46712
46713
46714 if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
46715
46716
46717
46718
46719
46720
46721
46722
46723
46724
46725
46726
46727
46728
46729
46730
46731 if (CaBundle::isOpensslParseSafe()) {
46732 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
46733
46734 if ($certDetails) {
46735 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
46736
46737 $this->retry = true;
46738 }
46739 } else {
46740 $this->io->writeError('');
46741 $this->io->writeError(sprintf(
46742 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
46743 PHP_VERSION
46744 ));
46745 }
46746 }
46747
46748 if ($this->retry) {
46749 $this->retry = false;
46750
46751 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46752
46753 if ($this->storeAuth && $this->config) {
46754 $authHelper = new AuthHelper($this->io, $this->config);
46755 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
46756 $this->storeAuth = false;
46757 }
46758
46759 return $result;
46760 }
46761
46762 if (false === $result) {
46763 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
46764 if (!empty($http_response_header[0])) {
46765 $e->setHeaders($http_response_header);
46766 }
46767
46768 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
46769 $this->degradedMode = true;
46770 $this->io->writeError('');
46771 $this->io->writeError(array(
46772 '<error>'.$e->getMessage().'</error>',
46773 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
46774 ));
46775
46776 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46777 }
46778
46779 throw $e;
46780 }
46781
46782 if (!empty($http_response_header[0])) {
46783 $this->lastHeaders = $http_response_header;
46784 }
46785
46786 return $result;
46787 }
46788
46789
46790
46791
46792
46793
46794
46795
46796
46797
46798 protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null)
46799 {
46800 try {
46801 $e = null;
46802 $result = file_get_contents($fileUrl, false, $context);
46803 } catch (\Throwable $e) {
46804 } catch (\Exception $e) {
46805 }
46806
46807 $responseHeaders = isset($http_response_header) ? $http_response_header : array();
46808
46809 if (null !== $e) {
46810 throw $e;
46811 }
46812
46813 return $result;
46814 }
46815
46816
46817
46818
46819
46820
46821
46822
46823
46824
46825
46826
46827 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
46828 {
46829 switch ($notificationCode) {
46830 case STREAM_NOTIFY_FAILURE:
46831 if (400 === $messageCode) {
46832
46833
46834 throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
46835 }
46836 break;
46837
46838 case STREAM_NOTIFY_FILE_SIZE_IS:
46839 $this->bytesMax = $bytesMax;
46840 break;
46841
46842 case STREAM_NOTIFY_PROGRESS:
46843 if ($this->bytesMax > 0 && $this->progress) {
46844 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
46845
46846 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
46847 $this->lastProgress = $progression;
46848 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
46849 }
46850 }
46851 break;
46852
46853 default:
46854 break;
46855 }
46856 }
46857
46858 protected function promptAuthAndRetry($httpStatus, $reason = null, $warning = null, $headers = array())
46859 {
46860 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
46861 $gitHubUtil = new GitHub($this->io, $this->config, null);
46862 $message = "\n";
46863
46864 $rateLimited = $gitHubUtil->isRateLimited($headers);
46865 if ($rateLimited) {
46866 $rateLimit = $gitHubUtil->getRateLimit($headers);
46867 if ($this->io->hasAuthentication($this->originUrl)) {
46868 $message = 'Review your configured GitHub OAuth token or enter a new one to go over the API rate limit.';
46869 } else {
46870 $message = 'Create a GitHub OAuth token to go over the API rate limit.';
46871 }
46872
46873 $message = sprintf(
46874 'GitHub API limit (%d calls/hr) is exhausted, could not fetch '.$this->fileUrl.'. '.$message.' You can also wait until %s for the rate limit to reset.',
46875 $rateLimit['limit'],
46876 $rateLimit['reset']
46877 )."\n";
46878 } else {
46879 $message .= 'Could not fetch '.$this->fileUrl.', please ';
46880 if ($this->io->hasAuthentication($this->originUrl)) {
46881 $message .= 'review your configured GitHub OAuth token or enter a new one to access private repos';
46882 } else {
46883 $message .= 'create a GitHub OAuth token to access private repos';
46884 }
46885 }
46886
46887 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
46888 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
46889 ) {
46890 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
46891 }
46892 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
46893 $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');
46894 $gitLabUtil = new GitLab($this->io, $this->config, null);
46895
46896 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && in_array($auth['password'], array('gitlab-ci-token', 'private-token', 'oauth2'), true)) {
46897 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
46898 }
46899
46900 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
46901 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
46902 ) {
46903 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
46904 }
46905 } elseif ($this->config && ($this->originUrl === 'bitbucket.org' || $this->originUrl === 'api.bitbucket.org')) {
46906 $askForOAuthToken = true;
46907 $this->originUrl = 'bitbucket.org';
46908
46909 if ($this->io->hasAuthentication($this->originUrl)) {
46910 $auth = $this->io->getAuthentication($this->originUrl);
46911 if ($auth['username'] !== 'x-token-auth') {
46912 $bitbucketUtil = new Bitbucket($this->io, $this->config);
46913 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
46914 if (!empty($accessToken)) {
46915 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
46916 $askForOAuthToken = false;
46917 }
46918 } else {
46919 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
46920 }
46921 }
46922
46923 if ($askForOAuthToken) {
46924 $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');
46925 $bitBucketUtil = new Bitbucket($this->io, $this->config);
46926 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
46927 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
46928 ) {
46929 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
46930 }
46931 }
46932 } else {
46933
46934 if ($httpStatus === 404) {
46935 return;
46936 }
46937
46938
46939 if (!$this->io->isInteractive()) {
46940 if ($httpStatus === 401) {
46941 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
46942 }
46943 if ($httpStatus === 403) {
46944 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
46945 }
46946
46947 throw new TransportException($message, $httpStatus);
46948 }
46949
46950 if ($this->io->hasAuthentication($this->originUrl)) {
46951 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
46952 }
46953
46954 $this->io->writeError('    Authentication required (<info>'.$this->originUrl.'</info>):');
46955 $username = $this->io->ask('      Username: ');
46956 $password = $this->io->askAndHideAnswer('      Password: ');
46957 $this->io->setAuthentication($this->originUrl, $username, $password);
46958 $this->storeAuth = $this->config->get('store-auths');
46959 }
46960
46961 $this->retry = true;
46962 throw new TransportException('RETRY');
46963 }
46964
46965 protected function getOptionsForUrl($originUrl, $additionalOptions)
46966 {
46967 $tlsOptions = array();
46968
46969
46970 if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
46971 $host = parse_url($this->fileUrl, PHP_URL_HOST);
46972
46973 if (PHP_VERSION_ID < 50304) {
46974
46975
46976
46977
46978
46979 if ($host === 'github.com' || $host === 'api.github.com') {
46980 $host = '*.github.com';
46981 }
46982 }
46983
46984 $tlsOptions['ssl']['CN_match'] = $host;
46985 $tlsOptions['ssl']['SNI_server_name'] = $host;
46986
46987 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
46988
46989 if (isset($this->peerCertificateMap[$urlAuthority])) {
46990
46991 $certMap = $this->peerCertificateMap[$urlAuthority];
46992
46993 $this->io->writeError('', true, IOInterface::DEBUG);
46994 $this->io->writeError(sprintf(
46995 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
46996 $certMap['cn'],
46997 $urlAuthority
46998 ), true, IOInterface::DEBUG);
46999
47000 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
47001 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
47002 } elseif (!CaBundle::isOpensslParseSafe() && $host === 'repo.packagist.org') {
47003
47004 $tlsOptions['ssl']['CN_match'] = 'packagist.org';
47005 }
47006 }
47007
47008 $headers = array();
47009
47010 if (extension_loaded('zlib')) {
47011 $headers[] = 'Accept-Encoding: gzip';
47012 }
47013
47014 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
47015 if (!$this->degradedMode) {
47016
47017
47018 $options['http']['protocol_version'] = 1.1;
47019 $headers[] = 'Connection: close';
47020 }
47021
47022 if ($this->io->hasAuthentication($originUrl)) {
47023 $authenticationDisplayMessage = null;
47024 $auth = $this->io->getAuthentication($originUrl);
47025 if ($auth['password'] === 'bearer') {
47026 $headers[] = 'Authorization: Bearer '.$auth['username'];
47027 } elseif ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
47028 $options['github-token'] = $auth['username'];
47029 $authenticationDisplayMessage = 'Using GitHub token authentication';
47030 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
47031 if ($auth['password'] === 'oauth2') {
47032 $headers[] = 'Authorization: Bearer '.$auth['username'];
47033 $authenticationDisplayMessage = 'Using GitLab OAuth token authentication';
47034 } elseif ($auth['password'] === 'private-token' || $auth['password'] === 'gitlab-ci-token') {
47035 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
47036 $authenticationDisplayMessage = 'Using GitLab private token authentication';
47037 }
47038 } elseif ('bitbucket.org' === $originUrl
47039 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
47040 ) {
47041 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
47042 $headers[] = 'Authorization: Bearer ' . $auth['password'];
47043 $authenticationDisplayMessage = 'Using Bitbucket OAuth token authentication';
47044 }
47045 } else {
47046 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
47047 $headers[] = 'Authorization: Basic '.$authStr;
47048 $authenticationDisplayMessage = 'Using HTTP basic authentication with username "' . $auth['username'] . '"';
47049 }
47050
47051 if ($authenticationDisplayMessage && !in_array($originUrl, $this->displayedOriginAuthentications, true)) {
47052 $this->io->writeError($authenticationDisplayMessage, true, IOInterface::DEBUG);
47053 $this->displayedOriginAuthentications[] = $originUrl;
47054 }
47055 }
47056
47057 $options['http']['follow_location'] = 0;
47058
47059 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
47060 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
47061 }
47062 foreach ($headers as $header) {
47063 $options['http']['header'][] = $header;
47064 }
47065
47066 return $options;
47067 }
47068
47069 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
47070 {
47071 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
47072 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
47073
47074 $targetUrl = $locationHeader;
47075 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
47076
47077 $targetUrl = $this->scheme.':'.$locationHeader;
47078 } elseif ('/' === $locationHeader[0]) {
47079
47080 $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
47081
47082
47083 $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
47084 } else {
47085
47086
47087 $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
47088 }
47089 }
47090
47091 if (!empty($targetUrl)) {
47092 $this->redirects++;
47093
47094 $this->io->writeError('', true, IOInterface::DEBUG);
47095 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $this->stripCredentialsFromUrl($targetUrl)), true, IOInterface::DEBUG);
47096
47097 $additionalOptions['redirects'] = $this->redirects;
47098
47099 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
47100 }
47101
47102 if (!$this->retry) {
47103 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
47104 $e->setHeaders($http_response_header);
47105 $e->setResponse($result);
47106
47107 throw $e;
47108 }
47109
47110 return false;
47111 }
47112
47113
47114
47115
47116
47117
47118 private function getTlsDefaults(array $options)
47119 {
47120 $ciphers = implode(':', array(
47121 'ECDHE-RSA-AES128-GCM-SHA256',
47122 'ECDHE-ECDSA-AES128-GCM-SHA256',
47123 'ECDHE-RSA-AES256-GCM-SHA384',
47124 'ECDHE-ECDSA-AES256-GCM-SHA384',
47125 'DHE-RSA-AES128-GCM-SHA256',
47126 'DHE-DSS-AES128-GCM-SHA256',
47127 'kEDH+AESGCM',
47128 'ECDHE-RSA-AES128-SHA256',
47129 'ECDHE-ECDSA-AES128-SHA256',
47130 'ECDHE-RSA-AES128-SHA',
47131 'ECDHE-ECDSA-AES128-SHA',
47132 'ECDHE-RSA-AES256-SHA384',
47133 'ECDHE-ECDSA-AES256-SHA384',
47134 'ECDHE-RSA-AES256-SHA',
47135 'ECDHE-ECDSA-AES256-SHA',
47136 'DHE-RSA-AES128-SHA256',
47137 'DHE-RSA-AES128-SHA',
47138 'DHE-DSS-AES128-SHA256',
47139 'DHE-RSA-AES256-SHA256',
47140 'DHE-DSS-AES256-SHA',
47141 'DHE-RSA-AES256-SHA',
47142 'AES128-GCM-SHA256',
47143 'AES256-GCM-SHA384',
47144 'AES128-SHA256',
47145 'AES256-SHA256',
47146 'AES128-SHA',
47147 'AES256-SHA',
47148 'AES',
47149 'CAMELLIA',
47150 'DES-CBC3-SHA',
47151 '!aNULL',
47152 '!eNULL',
47153 '!EXPORT',
47154 '!DES',
47155 '!RC4',
47156 '!MD5',
47157 '!PSK',
47158 '!aECDH',
47159 '!EDH-DSS-DES-CBC3-SHA',
47160 '!EDH-RSA-DES-CBC3-SHA',
47161 '!KRB5-DES-CBC3-SHA',
47162 ));
47163
47164
47165
47166
47167
47168
47169
47170 $defaults = array(
47171 'ssl' => array(
47172 'ciphers' => $ciphers,
47173 'verify_peer' => true,
47174 'verify_depth' => 7,
47175 'SNI_enabled' => true,
47176 'capture_peer_cert' => true,
47177 ),
47178 );
47179
47180 if (isset($options['ssl'])) {
47181 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
47182 }
47183
47184 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
47185
47186
47187
47188
47189
47190 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
47191 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
47192
47193 if (is_dir($result)) {
47194 $defaults['ssl']['capath'] = $result;
47195 } else {
47196 $defaults['ssl']['cafile'] = $result;
47197 }
47198 }
47199
47200 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
47201 throw new TransportException('The configured cafile was not valid or could not be read.');
47202 }
47203
47204 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
47205 throw new TransportException('The configured capath was not valid or could not be read.');
47206 }
47207
47208
47209
47210
47211 if (PHP_VERSION_ID >= 50413) {
47212 $defaults['ssl']['disable_compression'] = true;
47213 }
47214
47215 return $defaults;
47216 }
47217
47218
47219
47220
47221
47222
47223 private function getCertificateCnAndFp($url, $options)
47224 {
47225 if (PHP_VERSION_ID >= 50600) {
47226 throw new \BadMethodCallException(sprintf(
47227 '%s must not be used on PHP >= 5.6',
47228 __METHOD__
47229 ));
47230 }
47231
47232 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
47233 'ssl' => array(
47234 'capture_peer_cert' => true,
47235 'verify_peer' => false, 
47236 ), ),
47237 ));
47238
47239
47240
47241 if (false === $handle = @fopen($url, 'rb', false, $context)) {
47242 return;
47243 }
47244
47245
47246 fclose($handle);
47247 $handle = null;
47248
47249 $params = stream_context_get_params($context);
47250
47251 if (!empty($params['options']['ssl']['peer_certificate'])) {
47252 $peerCertificate = $params['options']['ssl']['peer_certificate'];
47253
47254 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
47255 return array(
47256 'cn' => $commonName,
47257 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
47258 );
47259 }
47260 }
47261 }
47262
47263 private function getUrlAuthority($url)
47264 {
47265 $defaultPorts = array(
47266 'ftp' => 21,
47267 'http' => 80,
47268 'https' => 443,
47269 'ssh2.sftp' => 22,
47270 'ssh2.scp' => 22,
47271 );
47272
47273 $scheme = parse_url($url, PHP_URL_SCHEME);
47274
47275 if (!isset($defaultPorts[$scheme])) {
47276 throw new \InvalidArgumentException(sprintf(
47277 'Could not get default port for unknown scheme: %s',
47278 $scheme
47279 ));
47280 }
47281
47282 $defaultPort = $defaultPorts[$scheme];
47283 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
47284
47285 return parse_url($url, PHP_URL_HOST).':'.$port;
47286 }
47287
47288
47289
47290
47291
47292
47293
47294
47295 private function isPublicBitBucketDownload($urlToBitBucketFile)
47296 {
47297 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
47298 if (strpos($domain, 'bitbucket.org') === false) {
47299
47300
47301 return true;
47302 }
47303
47304 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
47305
47306
47307
47308 $pathParts = explode('/', $path);
47309
47310 return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
47311 }
47312
47313 public static function outputWarnings(IOInterface $io, $url, $data)
47314 {
47315 foreach (array('warning', 'info') as $type) {
47316 if (empty($data[$type])) {
47317 continue;
47318 }
47319
47320 if (!empty($data[$type . '-versions'])) {
47321 $versionParser = new VersionParser();
47322 $constraint = $versionParser->parseConstraints($data[$type . '-versions']);
47323 $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion()));
47324 if (!$constraint->matches($composer)) {
47325 continue;
47326 }
47327 }
47328
47329 $io->writeError('<'.$type.'>'.ucfirst($type).' from '.$url.': '.$data[$type].'</'.$type.'>');
47330 }
47331 }
47332
47333 public static function getOrigin($urlOrPath)
47334 {
47335 $hostPort = parse_url($urlOrPath, PHP_URL_HOST);
47336 if (!$hostPort) {
47337 return $urlOrPath;
47338 }
47339 if (parse_url($urlOrPath, PHP_URL_PORT)) {
47340 $hostPort .= ':'.parse_url($urlOrPath, PHP_URL_PORT);
47341 }
47342
47343 return $hostPort;
47344 }
47345
47346 private function stripCredentialsFromUrl($url)
47347 {
47348
47349
47350 return preg_replace('{([&?]access_token=)[^&]+}', '$1***', $url);
47351 }
47352 }
47353 <?php
47354
47355
47356
47357
47358
47359
47360
47361
47362
47363
47364
47365 namespace Composer\Util;
47366
47367
47368
47369
47370
47371
47372 class Silencer
47373 {
47374
47375
47376
47377 private static $stack = array();
47378
47379
47380
47381
47382
47383
47384
47385 public static function suppress($mask = null)
47386 {
47387 if (!isset($mask)) {
47388 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
47389 }
47390 $old = error_reporting();
47391 self::$stack[] = $old;
47392 error_reporting($old & ~$mask);
47393
47394 return $old;
47395 }
47396
47397
47398
47399
47400 public static function restore()
47401 {
47402 if (!empty(self::$stack)) {
47403 error_reporting(array_pop(self::$stack));
47404 }
47405 }
47406
47407
47408
47409
47410
47411
47412
47413
47414
47415
47416 public static function call($callable )
47417 {
47418 try {
47419 self::suppress();
47420 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
47421 self::restore();
47422
47423 return $result;
47424 } catch (\Exception $e) {
47425
47426 self::restore();
47427 throw $e;
47428 }
47429 }
47430 }
47431 <?php
47432
47433
47434
47435
47436
47437
47438
47439
47440
47441
47442
47443 namespace Composer\Util;
47444
47445 use Composer\Spdx\SpdxLicenses;
47446
47447 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
47448
47449
47450
47451
47452 class SpdxLicense extends SpdxLicenses
47453 {
47454 }
47455 <?php
47456
47457
47458
47459
47460
47461
47462
47463
47464
47465
47466
47467 namespace Composer\Util;
47468
47469 use Composer\Composer;
47470
47471
47472
47473
47474
47475
47476
47477 final class StreamContextFactory
47478 {
47479
47480
47481
47482
47483
47484
47485
47486
47487
47488 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
47489 {
47490 $options = array('http' => array(
47491
47492 'follow_location' => 1,
47493 'max_redirects' => 20,
47494 ));
47495
47496
47497 if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
47498 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
47499 }
47500
47501
47502 if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
47503 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
47504 }
47505
47506
47507 if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
47508 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
47509 }
47510
47511
47512 if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
47513 $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
47514 if ($pattern->test($url)) {
47515 unset($proxy);
47516 }
47517 }
47518
47519 if (!empty($proxy)) {
47520 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
47521 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
47522
47523 if (isset($proxy['port'])) {
47524 $proxyURL .= ":" . $proxy['port'];
47525 } elseif ('http://' == substr($proxyURL, 0, 7)) {
47526 $proxyURL .= ":80";
47527 } elseif ('https://' == substr($proxyURL, 0, 8)) {
47528 $proxyURL .= ":443";
47529 }
47530
47531
47532 $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
47533
47534 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
47535 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
47536 }
47537
47538 $options['http']['proxy'] = $proxyURL;
47539
47540
47541 switch (parse_url($url, PHP_URL_SCHEME)) {
47542 case 'http': 
47543 $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
47544 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
47545 $options['http']['request_fulluri'] = true;
47546 }
47547 break;
47548 case 'https': 
47549 $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
47550 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
47551 $options['http']['request_fulluri'] = true;
47552 }
47553 break;
47554 }
47555
47556
47557 if ('https' === parse_url($url, PHP_URL_SCHEME)) {
47558 $options['ssl']['SNI_enabled'] = true;
47559 if (PHP_VERSION_ID < 50600) {
47560 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
47561 }
47562 }
47563
47564
47565 if (isset($proxy['user'])) {
47566 $auth = rawurldecode($proxy['user']);
47567 if (isset($proxy['pass'])) {
47568 $auth .= ':' . rawurldecode($proxy['pass']);
47569 }
47570 $auth = base64_encode($auth);
47571
47572
47573 if (isset($defaultOptions['http']['header'])) {
47574 if (is_string($defaultOptions['http']['header'])) {
47575 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
47576 }
47577 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
47578 } else {
47579 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
47580 }
47581 }
47582 }
47583
47584 $options = array_replace_recursive($options, $defaultOptions);
47585
47586 if (isset($options['http']['header'])) {
47587 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
47588 }
47589
47590 if (defined('HHVM_VERSION')) {
47591 $phpVersion = 'HHVM ' . HHVM_VERSION;
47592 } else {
47593 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
47594 }
47595
47596 if (!isset($options['http']['header']) || false === stripos(implode('', $options['http']['header']), 'user-agent')) {
47597 $options['http']['header'][] = sprintf(
47598 'User-Agent: Composer/%s (%s; %s; %s%s)',
47599 Composer::getVersion(),
47600 function_exists('php_uname') ? php_uname('s') : 'Unknown',
47601 function_exists('php_uname') ? php_uname('r') : 'Unknown',
47602 $phpVersion,
47603 getenv('CI') ? '; CI' : ''
47604 );
47605 }
47606
47607 return stream_context_create($options, $defaultParams);
47608 }
47609
47610
47611
47612
47613
47614
47615
47616
47617
47618
47619
47620 private static function fixHttpHeaderField($header)
47621 {
47622 if (!is_array($header)) {
47623 $header = explode("\r\n", $header);
47624 }
47625 uasort($header, function ($el) {
47626 return stripos($el, 'content-type') === 0 ? 1 : -1;
47627 });
47628
47629 return $header;
47630 }
47631 }
47632 <?php
47633
47634
47635
47636
47637
47638
47639
47640
47641
47642
47643
47644 namespace Composer\Util;
47645
47646 use Composer\Config;
47647 use Composer\IO\IOInterface;
47648
47649
47650
47651
47652
47653 class Svn
47654 {
47655 const MAX_QTY_AUTH_TRIES = 5;
47656
47657
47658
47659
47660 protected $credentials;
47661
47662
47663
47664
47665 protected $hasAuth;
47666
47667
47668
47669
47670 protected $io;
47671
47672
47673
47674
47675 protected $url;
47676
47677
47678
47679
47680 protected $cacheCredentials = true;
47681
47682
47683
47684
47685 protected $process;
47686
47687
47688
47689
47690 protected $qtyAuthTries = 0;
47691
47692
47693
47694
47695 protected $config;
47696
47697
47698
47699
47700 private static $version;
47701
47702
47703
47704
47705
47706
47707
47708 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
47709 {
47710 $this->url = $url;
47711 $this->io = $io;
47712 $this->config = $config;
47713 $this->process = $process ?: new ProcessExecutor($io);
47714 }
47715
47716 public static function cleanEnv()
47717 {
47718
47719 putenv("DYLD_LIBRARY_PATH");
47720 unset($_SERVER['DYLD_LIBRARY_PATH']);
47721 }
47722
47723
47724
47725
47726
47727
47728
47729
47730
47731
47732
47733
47734
47735
47736 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
47737 {
47738
47739 $this->config->prohibitUrlByConfig($url, $this->io);
47740
47741 return $this->executeWithAuthRetry($command, $cwd, $url, $path, $verbose);
47742 }
47743
47744
47745
47746
47747
47748
47749
47750
47751
47752
47753
47754
47755
47756 public function executeLocal($command, $path, $cwd = null, $verbose = false)
47757 {
47758
47759 return $this->executeWithAuthRetry($command, $cwd, '', $path, $verbose);
47760 }
47761
47762 private function executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose)
47763 {
47764
47765 $command = $this->getCommand($svnCommand, $url, $path);
47766
47767 $output = null;
47768 $io = $this->io;
47769 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
47770 if ($type !== 'out') {
47771 return;
47772 }
47773 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
47774 return;
47775 }
47776 $output .= $buffer;
47777 if ($verbose) {
47778 $io->writeError($buffer, false);
47779 }
47780 };
47781 $status = $this->process->execute($command, $handler, $cwd);
47782 if (0 === $status) {
47783 return $output;
47784 }
47785
47786 $errorOutput = $this->process->getErrorOutput();
47787 $fullOutput = implode("\n", array($output, $errorOutput));
47788
47789
47790 if (false === stripos($fullOutput, 'Could not authenticate to server:')
47791 && false === stripos($fullOutput, 'authorization failed')
47792 && false === stripos($fullOutput, 'svn: E170001:')
47793 && false === stripos($fullOutput, 'svn: E215004:')) {
47794 throw new \RuntimeException($fullOutput);
47795 }
47796
47797 if (!$this->hasAuth()) {
47798 $this->doAuthDance();
47799 }
47800
47801
47802 if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
47803
47804 return $this->executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose);
47805 }
47806
47807 throw new \RuntimeException(
47808 'wrong credentials provided ('.$fullOutput.')'
47809 );
47810 }
47811
47812
47813
47814
47815 public function setCacheCredentials($cacheCredentials)
47816 {
47817 $this->cacheCredentials = $cacheCredentials;
47818 }
47819
47820
47821
47822
47823
47824
47825
47826 protected function doAuthDance()
47827 {
47828
47829 if (!$this->io->isInteractive()) {
47830 throw new \RuntimeException(
47831 'can not ask for authentication in non interactive mode'
47832 );
47833 }
47834
47835 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
47836
47837 $this->hasAuth = true;
47838 $this->credentials['username'] = $this->io->ask("Username: ");
47839 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
47840
47841 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
47842
47843 return $this;
47844 }
47845
47846
47847
47848
47849
47850
47851
47852
47853
47854
47855 protected function getCommand($cmd, $url, $path = null)
47856 {
47857 $cmd = sprintf(
47858 '%s %s%s -- %s',
47859 $cmd,
47860 '--non-interactive ',
47861 $this->getCredentialString(),
47862 ProcessExecutor::escape($url)
47863 );
47864
47865 if ($path) {
47866 $cmd .= ' ' . ProcessExecutor::escape($path);
47867 }
47868
47869 return $cmd;
47870 }
47871
47872
47873
47874
47875
47876
47877
47878
47879 protected function getCredentialString()
47880 {
47881 if (!$this->hasAuth()) {
47882 return '';
47883 }
47884
47885 return sprintf(
47886 ' %s--username %s --password %s ',
47887 $this->getAuthCache(),
47888 ProcessExecutor::escape($this->getUsername()),
47889 ProcessExecutor::escape($this->getPassword())
47890 );
47891 }
47892
47893
47894
47895
47896
47897
47898
47899 protected function getPassword()
47900 {
47901 if ($this->credentials === null) {
47902 throw new \LogicException("No svn auth detected.");
47903 }
47904
47905 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
47906 }
47907
47908
47909
47910
47911
47912
47913
47914 protected function getUsername()
47915 {
47916 if ($this->credentials === null) {
47917 throw new \LogicException("No svn auth detected.");
47918 }
47919
47920 return $this->credentials['username'];
47921 }
47922
47923
47924
47925
47926
47927
47928 protected function hasAuth()
47929 {
47930 if (null !== $this->hasAuth) {
47931 return $this->hasAuth;
47932 }
47933
47934 if (false === $this->createAuthFromConfig()) {
47935 $this->createAuthFromUrl();
47936 }
47937
47938 return $this->hasAuth;
47939 }
47940
47941
47942
47943
47944
47945
47946 protected function getAuthCache()
47947 {
47948 return $this->cacheCredentials ? '' : '--no-auth-cache ';
47949 }
47950
47951
47952
47953
47954
47955
47956 private function createAuthFromConfig()
47957 {
47958 if (!$this->config->has('http-basic')) {
47959 return $this->hasAuth = false;
47960 }
47961
47962 $authConfig = $this->config->get('http-basic');
47963
47964 $host = parse_url($this->url, PHP_URL_HOST);
47965 if (isset($authConfig[$host])) {
47966 $this->credentials['username'] = $authConfig[$host]['username'];
47967 $this->credentials['password'] = $authConfig[$host]['password'];
47968
47969 return $this->hasAuth = true;
47970 }
47971
47972 return $this->hasAuth = false;
47973 }
47974
47975
47976
47977
47978
47979
47980 private function createAuthFromUrl()
47981 {
47982 $uri = parse_url($this->url);
47983 if (empty($uri['user'])) {
47984 return $this->hasAuth = false;
47985 }
47986
47987 $this->credentials['username'] = $uri['user'];
47988 if (!empty($uri['pass'])) {
47989 $this->credentials['password'] = $uri['pass'];
47990 }
47991
47992 return $this->hasAuth = true;
47993 }
47994
47995
47996
47997
47998
47999
48000 public function binaryVersion()
48001 {
48002 if (!self::$version) {
48003 if (0 === $this->process->execute('svn --version', $output)) {
48004 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match)) {
48005 self::$version = $match[1];
48006 }
48007 }
48008 }
48009
48010 return self::$version;
48011 }
48012 }
48013 <?php
48014
48015
48016
48017
48018
48019
48020
48021
48022
48023
48024
48025 namespace Composer\Util;
48026
48027 use Composer\CaBundle\CaBundle;
48028
48029
48030
48031
48032 final class TlsHelper
48033 {
48034
48035
48036
48037
48038
48039
48040
48041
48042
48043 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
48044 {
48045 $names = self::getCertificateNames($certificate);
48046
48047 if (empty($names)) {
48048 return false;
48049 }
48050
48051 $combinedNames = array_merge($names['san'], array($names['cn']));
48052 $hostname = strtolower($hostname);
48053
48054 foreach ($combinedNames as $certName) {
48055 $matcher = self::certNameMatcher($certName);
48056
48057 if ($matcher && $matcher($hostname)) {
48058 $cn = $names['cn'];
48059
48060 return true;
48061 }
48062 }
48063
48064 return false;
48065 }
48066
48067
48068
48069
48070
48071
48072
48073
48074 public static function getCertificateNames($certificate)
48075 {
48076 if (is_array($certificate)) {
48077 $info = $certificate;
48078 } elseif (CaBundle::isOpensslParseSafe()) {
48079 $info = openssl_x509_parse($certificate, false);
48080 }
48081
48082 if (!isset($info['subject']['commonName'])) {
48083 return null;
48084 }
48085
48086 $commonName = strtolower($info['subject']['commonName']);
48087 $subjectAltNames = array();
48088
48089 if (isset($info['extensions']['subjectAltName'])) {
48090 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
48091 $subjectAltNames = array_filter(array_map(function ($name) {
48092 if (0 === strpos($name, 'DNS:')) {
48093 return strtolower(ltrim(substr($name, 4)));
48094 }
48095
48096 return null;
48097 }, $subjectAltNames));
48098 $subjectAltNames = array_values($subjectAltNames);
48099 }
48100
48101 return array(
48102 'cn' => $commonName,
48103 'san' => $subjectAltNames,
48104 );
48105 }
48106
48107
48108
48109
48110
48111
48112
48113
48114
48115
48116
48117
48118
48119
48120
48121
48122
48123
48124
48125
48126
48127
48128
48129
48130
48131
48132
48133
48134
48135
48136
48137
48138
48139
48140
48141
48142
48143
48144
48145
48146 public static function getCertificateFingerprint($certificate)
48147 {
48148 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
48149 $pubkeypem = $pubkeydetails['key'];
48150
48151 $start = '-----BEGIN PUBLIC KEY-----';
48152 $end = '-----END PUBLIC KEY-----';
48153 $pemtrim = substr($pubkeypem, strpos($pubkeypem, $start) + strlen($start), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
48154 $der = base64_decode($pemtrim);
48155
48156 return sha1($der);
48157 }
48158
48159
48160
48161
48162
48163
48164
48165
48166
48167 public static function isOpensslParseSafe()
48168 {
48169 return CaBundle::isOpensslParseSafe();
48170 }
48171
48172
48173
48174
48175
48176
48177
48178
48179 private static function certNameMatcher($certName)
48180 {
48181 $wildcards = substr_count($certName, '*');
48182
48183 if (0 === $wildcards) {
48184
48185 return function ($hostname) use ($certName) {
48186 return $hostname === $certName;
48187 };
48188 }
48189
48190 if (1 === $wildcards) {
48191 $components = explode('.', $certName);
48192
48193 if (3 > count($components)) {
48194
48195 return;
48196 }
48197
48198 $firstComponent = $components[0];
48199
48200
48201 if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
48202 return;
48203 }
48204
48205 $wildcardRegex = preg_quote($certName);
48206 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
48207 $wildcardRegex = "{^{$wildcardRegex}$}";
48208
48209 return function ($hostname) use ($wildcardRegex) {
48210 return 1 === preg_match($wildcardRegex, $hostname);
48211 };
48212 }
48213 }
48214 }
48215 <?php
48216
48217
48218
48219
48220
48221
48222
48223
48224
48225
48226
48227 namespace Composer\Util;
48228
48229 use Composer\Config;
48230
48231
48232
48233
48234 class Url
48235 {
48236 public static function updateDistReference(Config $config, $url, $ref)
48237 {
48238 $host = parse_url($url, PHP_URL_HOST);
48239
48240 if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
48241 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
48242
48243 $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
48244 } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
48245
48246 $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
48247 } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
48248
48249 $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
48250 }
48251 } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
48252 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
48253
48254 $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4];
48255 }
48256 } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
48257 if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
48258
48259 $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
48260 }
48261 } elseif (in_array($host, $config->get('github-domains'), true)) {
48262 $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url);
48263 } elseif (in_array($host, $config->get('gitlab-domains'), true)) {
48264 $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url);
48265 }
48266
48267 return $url;
48268 }
48269 }
48270 <?php
48271
48272
48273
48274
48275
48276
48277
48278
48279
48280
48281
48282 namespace Composer\Util;
48283
48284
48285
48286
48287 class Zip
48288 {
48289
48290
48291
48292
48293
48294
48295
48296 public static function getComposerJson($pathToZip)
48297 {
48298 if (!extension_loaded('zip')) {
48299 throw new \RuntimeException('The Zip Util requires PHP\'s zip extension');
48300 }
48301
48302 $zip = new \ZipArchive();
48303 if ($zip->open($pathToZip) !== true) {
48304 return null;
48305 }
48306
48307 if (0 == $zip->numFiles) {
48308 $zip->close();
48309
48310 return null;
48311 }
48312
48313 $foundFileIndex = self::locateFile($zip, 'composer.json');
48314 if (false === $foundFileIndex) {
48315 $zip->close();
48316
48317 return null;
48318 }
48319
48320 $content = null;
48321 $configurationFileName = $zip->getNameIndex($foundFileIndex);
48322 $stream = $zip->getStream($configurationFileName);
48323
48324 if (false !== $stream) {
48325 $content = stream_get_contents($stream);
48326 }
48327
48328 $zip->close();
48329
48330 return $content;
48331 }
48332
48333
48334
48335
48336
48337
48338
48339
48340
48341 private static function locateFile(\ZipArchive $zip, $filename)
48342 {
48343 $indexOfShortestMatch = false;
48344 $lengthOfShortestMatch = -1;
48345
48346 for ($i = 0; $i < $zip->numFiles; $i++) {
48347 $stat = $zip->statIndex($i);
48348 if (strcmp(basename($stat['name']), $filename) === 0) {
48349 $directoryName = dirname($stat['name']);
48350 if ($directoryName === '.') {
48351
48352
48353 return $i;
48354 }
48355
48356 if (strpos($directoryName, '\\') !== false ||
48357 strpos($directoryName, '/') !== false) {
48358
48359 continue;
48360 }
48361
48362 $length = strlen($stat['name']);
48363 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
48364
48365 $contents = $zip->getFromIndex($i);
48366 if ($contents !== false) {
48367 $indexOfShortestMatch = $i;
48368 $lengthOfShortestMatch = $length;
48369 }
48370 }
48371 }
48372 }
48373
48374 return $indexOfShortestMatch;
48375 }
48376 }
48377 <?php
48378
48379
48380
48381
48382
48383
48384
48385
48386
48387
48388
48389 namespace Composer;
48390
48391 use Symfony\Component\Console\Output\OutputInterface;
48392
48393 trigger_error('The ' . __NAMESPACE__ . '\XdebugHandler class is deprecated, use Composer\XdebugHandler\XdebugHandler instead,', E_USER_DEPRECATED);
48394
48395
48396
48397
48398 class XdebugHandler extends XdebugHandler\XdebugHandler
48399 {
48400 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
48401 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
48402
48403 public function __construct(OutputInterface $output)
48404 {
48405 parent::__construct('composer', '--ansi');
48406 }
48407 }
48408 <?php
48409
48410
48411
48412
48413
48414
48415
48416
48417
48418
48419
48420 function includeIfExists($file)
48421 {
48422 return file_exists($file) ? include $file : false;
48423 }
48424
48425 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
48426 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
48427 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
48428 exit(1);
48429 }
48430
48431 return $loader;
48432 <?php
48433
48434 /*
48435  * This file is part of Composer.
48436  *
48437  * (c) Nils Adermann <naderman@naderman.de>
48438  *     Jordi Boggiano <j.boggiano@seld.be>
48439  *
48440  * For the full copyright and license information, please view the LICENSE
48441  * file that was distributed with this source code.
48442  */
48443
48444 namespace Composer\Autoload;
48445
48446 /**
48447  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
48448  *
48449  *     $loader = new \Composer\Autoload\ClassLoader();
48450  *
48451  *     // register classes with namespaces
48452  *     $loader->add('Symfony\Component', __DIR__.'/component');
48453  *     $loader->add('Symfony',           __DIR__.'/framework');
48454  *
48455  *     // activate the autoloader
48456  *     $loader->register();
48457  *
48458  *     // to enable searching the include path (eg. for PEAR packages)
48459  *     $loader->setUseIncludePath(true);
48460  *
48461  * In this example, if you try to use a class in the Symfony\Component
48462  * namespace or one of its children (Symfony\Component\Console for instance),
48463  * the autoloader will first look for the class under the component/
48464  * directory, and it will then fallback to the framework/ directory if not
48465  * found before giving up.
48466  *
48467  * This class is loosely based on the Symfony UniversalClassLoader.
48468  *
48469  * @author Fabien Potencier <fabien@symfony.com>
48470  * @author Jordi Boggiano <j.boggiano@seld.be>
48471  * @see    http://www.php-fig.org/psr/psr-0/
48472  * @see    http://www.php-fig.org/psr/psr-4/
48473  */
48474 class ClassLoader
48475 {
48476     // PSR-4
48477     private $prefixLengthsPsr4 = array();
48478     private $prefixDirsPsr4 = array();
48479     private $fallbackDirsPsr4 = array();
48480
48481     // PSR-0
48482     private $prefixesPsr0 = array();
48483     private $fallbackDirsPsr0 = array();
48484
48485     private $useIncludePath = false;
48486     private $classMap = array();
48487     private $classMapAuthoritative = false;
48488     private $missingClasses = array();
48489     private $apcuPrefix;
48490
48491     public function getPrefixes()
48492     {
48493         if (!empty($this->prefixesPsr0)) {
48494             return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
48495         }
48496
48497         return array();
48498     }
48499
48500     public function getPrefixesPsr4()
48501     {
48502         return $this->prefixDirsPsr4;
48503     }
48504
48505     public function getFallbackDirs()
48506     {
48507         return $this->fallbackDirsPsr0;
48508     }
48509
48510     public function getFallbackDirsPsr4()
48511     {
48512         return $this->fallbackDirsPsr4;
48513     }
48514
48515     public function getClassMap()
48516     {
48517         return $this->classMap;
48518     }
48519
48520     /**
48521      * @param array $classMap Class to filename map
48522      */
48523     public function addClassMap(array $classMap)
48524     {
48525         if ($this->classMap) {
48526             $this->classMap = array_merge($this->classMap, $classMap);
48527         } else {
48528             $this->classMap = $classMap;
48529         }
48530     }
48531
48532     /**
48533      * Registers a set of PSR-0 directories for a given prefix, either
48534      * appending or prepending to the ones previously set for this prefix.
48535      *
48536      * @param string       $prefix  The prefix
48537      * @param array|string $paths   The PSR-0 root directories
48538      * @param bool         $prepend Whether to prepend the directories
48539      */
48540     public function add($prefix, $paths, $prepend = false)
48541     {
48542         if (!$prefix) {
48543             if ($prepend) {
48544                 $this->fallbackDirsPsr0 = array_merge(
48545                     (array) $paths,
48546                     $this->fallbackDirsPsr0
48547                 );
48548             } else {
48549                 $this->fallbackDirsPsr0 = array_merge(
48550                     $this->fallbackDirsPsr0,
48551                     (array) $paths
48552                 );
48553             }
48554
48555             return;
48556         }
48557
48558         $first = $prefix[0];
48559         if (!isset($this->prefixesPsr0[$first][$prefix])) {
48560             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
48561
48562             return;
48563         }
48564         if ($prepend) {
48565             $this->prefixesPsr0[$first][$prefix] = array_merge(
48566                 (array) $paths,
48567                 $this->prefixesPsr0[$first][$prefix]
48568             );
48569         } else {
48570             $this->prefixesPsr0[$first][$prefix] = array_merge(
48571                 $this->prefixesPsr0[$first][$prefix],
48572                 (array) $paths
48573             );
48574         }
48575     }
48576
48577     /**
48578      * Registers a set of PSR-4 directories for a given namespace, either
48579      * appending or prepending to the ones previously set for this namespace.
48580      *
48581      * @param string       $prefix  The prefix/namespace, with trailing '\\'
48582      * @param array|string $paths   The PSR-4 base directories
48583      * @param bool         $prepend Whether to prepend the directories
48584      *
48585      * @throws \InvalidArgumentException
48586      */
48587     public function addPsr4($prefix, $paths, $prepend = false)
48588     {
48589         if (!$prefix) {
48590             // Register directories for the root namespace.
48591             if ($prepend) {
48592                 $this->fallbackDirsPsr4 = array_merge(
48593                     (array) $paths,
48594                     $this->fallbackDirsPsr4
48595                 );
48596             } else {
48597                 $this->fallbackDirsPsr4 = array_merge(
48598                     $this->fallbackDirsPsr4,
48599                     (array) $paths
48600                 );
48601             }
48602         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
48603             // Register directories for a new namespace.
48604             $length = strlen($prefix);
48605             if ('\\' !== $prefix[$length - 1]) {
48606                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
48607             }
48608             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
48609             $this->prefixDirsPsr4[$prefix] = (array) $paths;
48610         } elseif ($prepend) {
48611             // Prepend directories for an already registered namespace.
48612             $this->prefixDirsPsr4[$prefix] = array_merge(
48613                 (array) $paths,
48614                 $this->prefixDirsPsr4[$prefix]
48615             );
48616         } else {
48617             // Append directories for an already registered namespace.
48618             $this->prefixDirsPsr4[$prefix] = array_merge(
48619                 $this->prefixDirsPsr4[$prefix],
48620                 (array) $paths
48621             );
48622         }
48623     }
48624
48625     /**
48626      * Registers a set of PSR-0 directories for a given prefix,
48627      * replacing any others previously set for this prefix.
48628      *
48629      * @param string       $prefix The prefix
48630      * @param array|string $paths  The PSR-0 base directories
48631      */
48632     public function set($prefix, $paths)
48633     {
48634         if (!$prefix) {
48635             $this->fallbackDirsPsr0 = (array) $paths;
48636         } else {
48637             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
48638         }
48639     }
48640
48641     /**
48642      * Registers a set of PSR-4 directories for a given namespace,
48643      * replacing any others previously set for this namespace.
48644      *
48645      * @param string       $prefix The prefix/namespace, with trailing '\\'
48646      * @param array|string $paths  The PSR-4 base directories
48647      *
48648      * @throws \InvalidArgumentException
48649      */
48650     public function setPsr4($prefix, $paths)
48651     {
48652         if (!$prefix) {
48653             $this->fallbackDirsPsr4 = (array) $paths;
48654         } else {
48655             $length = strlen($prefix);
48656             if ('\\' !== $prefix[$length - 1]) {
48657                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
48658             }
48659             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
48660             $this->prefixDirsPsr4[$prefix] = (array) $paths;
48661         }
48662     }
48663
48664     /**
48665      * Turns on searching the include path for class files.
48666      *
48667      * @param bool $useIncludePath
48668      */
48669     public function setUseIncludePath($useIncludePath)
48670     {
48671         $this->useIncludePath = $useIncludePath;
48672     }
48673
48674     /**
48675      * Can be used to check if the autoloader uses the include path to check
48676      * for classes.
48677      *
48678      * @return bool
48679      */
48680     public function getUseIncludePath()
48681     {
48682         return $this->useIncludePath;
48683     }
48684
48685     /**
48686      * Turns off searching the prefix and fallback directories for classes
48687      * that have not been registered with the class map.
48688      *
48689      * @param bool $classMapAuthoritative
48690      */
48691     public function setClassMapAuthoritative($classMapAuthoritative)
48692     {
48693         $this->classMapAuthoritative = $classMapAuthoritative;
48694     }
48695
48696     /**
48697      * Should class lookup fail if not found in the current class map?
48698      *
48699      * @return bool
48700      */
48701     public function isClassMapAuthoritative()
48702     {
48703         return $this->classMapAuthoritative;
48704     }
48705
48706     /**
48707      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
48708      *
48709      * @param string|null $apcuPrefix
48710      */
48711     public function setApcuPrefix($apcuPrefix)
48712     {
48713         $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
48714     }
48715
48716     /**
48717      * The APCu prefix in use, or null if APCu caching is not enabled.
48718      *
48719      * @return string|null
48720      */
48721     public function getApcuPrefix()
48722     {
48723         return $this->apcuPrefix;
48724     }
48725
48726     /**
48727      * Registers this instance as an autoloader.
48728      *
48729      * @param bool $prepend Whether to prepend the autoloader or not
48730      */
48731     public function register($prepend = false)
48732     {
48733         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
48734     }
48735
48736     /**
48737      * Unregisters this instance as an autoloader.
48738      */
48739     public function unregister()
48740     {
48741         spl_autoload_unregister(array($this, 'loadClass'));
48742     }
48743
48744     /**
48745      * Loads the given class or interface.
48746      *
48747      * @param  string    $class The name of the class
48748      * @return bool|null True if loaded, null otherwise
48749      */
48750     public function loadClass($class)
48751     {
48752         if ($file = $this->findFile($class)) {
48753             includeFile($file);
48754
48755             return true;
48756         }
48757     }
48758
48759     /**
48760      * Finds the path to the file where the class is defined.
48761      *
48762      * @param string $class The name of the class
48763      *
48764      * @return string|false The path if found, false otherwise
48765      */
48766     public function findFile($class)
48767     {
48768         // class map lookup
48769         if (isset($this->classMap[$class])) {
48770             return $this->classMap[$class];
48771         }
48772         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
48773             return false;
48774         }
48775         if (null !== $this->apcuPrefix) {
48776             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
48777             if ($hit) {
48778                 return $file;
48779             }
48780         }
48781
48782         $file = $this->findFileWithExtension($class, '.php');
48783
48784         // Search for Hack files if we are running on HHVM
48785         if (false === $file && defined('HHVM_VERSION')) {
48786             $file = $this->findFileWithExtension($class, '.hh');
48787         }
48788
48789         if (null !== $this->apcuPrefix) {
48790             apcu_add($this->apcuPrefix.$class, $file);
48791         }
48792
48793         if (false === $file) {
48794             // Remember that this class does not exist.
48795             $this->missingClasses[$class] = true;
48796         }
48797
48798         return $file;
48799     }
48800
48801     private function findFileWithExtension($class, $ext)
48802     {
48803         // PSR-4 lookup
48804         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
48805
48806         $first = $class[0];
48807         if (isset($this->prefixLengthsPsr4[$first])) {
48808             $subPath = $class;
48809             while (false !== $lastPos = strrpos($subPath, '\\')) {
48810                 $subPath = substr($subPath, 0, $lastPos);
48811                 $search = $subPath . '\\';
48812                 if (isset($this->prefixDirsPsr4[$search])) {
48813                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
48814                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
48815                         if (file_exists($file = $dir . $pathEnd)) {
48816                             return $file;
48817                         }
48818                     }
48819                 }
48820             }
48821         }
48822
48823         // PSR-4 fallback dirs
48824         foreach ($this->fallbackDirsPsr4 as $dir) {
48825             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
48826                 return $file;
48827             }
48828         }
48829
48830         // PSR-0 lookup
48831         if (false !== $pos = strrpos($class, '\\')) {
48832             // namespaced class name
48833             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
48834                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
48835         } else {
48836             // PEAR-like class name
48837             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
48838         }
48839
48840         if (isset($this->prefixesPsr0[$first])) {
48841             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
48842                 if (0 === strpos($class, $prefix)) {
48843                     foreach ($dirs as $dir) {
48844                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
48845                             return $file;
48846                         }
48847                     }
48848                 }
48849             }
48850         }
48851
48852         // PSR-0 fallback dirs
48853         foreach ($this->fallbackDirsPsr0 as $dir) {
48854             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
48855                 return $file;
48856             }
48857         }
48858
48859         // PSR-0 include paths.
48860         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
48861             return $file;
48862         }
48863
48864         return false;
48865     }
48866 }
48867
48868 /**
48869  * Scope isolated include.
48870  *
48871  * Prevents access to $this/self from included files.
48872  */
48873 function includeFile($file)
48874 {
48875     include $file;
48876 }
48877 {
48878     "$schema": "http://json-schema.org/draft-04/schema#",
48879     "description": "A representation of packages metadata.",
48880     "type": "object",
48881     "oneOf": [
48882         { "required": [ "packages" ] },
48883         { "required": [ "providers" ] },
48884         { "required": [ "provider-includes", "providers-url" ] }
48885     ],
48886     "properties": {
48887         "packages": {
48888             "type": ["object", "array"],
48889             "description": "A hashmap of package names in the form of <vendor>/<name>.",
48890             "additionalProperties": { "$ref": "#/definitions/versions" }
48891         },
48892         "providers-url": {
48893             "type": "string",
48894             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
48895         },
48896         "provider-includes": {
48897             "type": "object",
48898             "description": "A hashmap of provider listings.",
48899             "additionalProperties": { "$ref": "#/definitions/provider" }
48900         },
48901         "providers": {
48902             "type": "object",
48903             "description": "A hashmap of package names in the form of <vendor>/<name>.",
48904             "additionalProperties": { "$ref": "#/definitions/provider" }
48905         },
48906         "notify-batch": {
48907             "type": "string",
48908             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
48909         },
48910         "search": {
48911             "type": "string",
48912             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
48913         },
48914         "warning": {
48915             "type": "string",
48916             "description": "A message that will be output by Composer as a warning when this source is consulted."
48917         }
48918     },
48919     "definitions": {
48920         "versions": {
48921             "type": "object",
48922             "description": "A hashmap of versions and their metadata.",
48923             "additionalProperties": { "$ref": "#/definitions/version" }
48924         },
48925         "version": {
48926             "type": "object",
48927             "oneOf": [
48928                 { "$ref": "#/definitions/package" },
48929                 { "$ref": "#/definitions/metapackage" }
48930             ]
48931         },
48932         "package-base": {
48933             "properties": {
48934                 "name": { "type": "string" },
48935                 "type": { "type": "string" },
48936                 "version": { "type": "string" },
48937                 "version_normalized": {
48938                     "type": "string",
48939                     "description": "Normalized version, optional but can save computational time on client side."
48940                 },
48941                 "autoload": { "type": "object" },
48942                 "require": { "type": "object" },
48943                 "replace": { "type": "object" },
48944                 "conflict": { "type": "object" },
48945                 "provide": { "type": "object" },
48946                 "time": { "type": "string" }
48947             },
48948             "additionalProperties": true
48949         },
48950         "package": {
48951             "allOf": [
48952                 { "$ref": "#/definitions/package-base" },
48953                 {
48954                     "properties": {
48955                         "dist": { "type": "object" },
48956                         "source": { "type": "object" }
48957                     }
48958                 },
48959                 { "oneOf": [
48960                     { "required": [ "name", "version", "source" ] },
48961                     { "required": [ "name", "version", "dist" ] }
48962                 ] }
48963             ]
48964         },
48965         "metapackage": {
48966             "allOf": [
48967                 { "$ref": "#/definitions/package-base" },
48968                 {
48969                     "properties": {
48970                         "type": { "type": "string", "enum": [ "metapackage" ] }
48971                     },
48972                     "required": [ "name", "version", "type" ]
48973                 }
48974             ]
48975         },
48976         "provider": {
48977             "type": "object",
48978             "properties": {
48979                 "sha256": {
48980                     "type": "string",
48981                     "description": "Hash value that can be used to validate the resource."
48982                 }
48983             }
48984         }
48985     }
48986 }
48987 {
48988     "$schema": "http://json-schema.org/draft-04/schema#",
48989     "name": "Package",
48990     "type": "object",
48991     "additionalProperties": false,
48992     "required": [ "name", "description" ],
48993     "properties": {
48994         "name": {
48995             "type": "string",
48996             "description": "Package name, including 'vendor-name/' prefix."
48997         },
48998         "type": {
48999             "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.",
49000             "type": "string",
49001             "pattern": "^[a-z0-9-]+$"
49002         },
49003         "target-dir": {
49004             "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.",
49005             "type": "string"
49006         },
49007         "description": {
49008             "type": "string",
49009             "description": "Short package description."
49010         },
49011         "keywords": {
49012             "type": "array",
49013             "items": {
49014                 "type": "string",
49015                 "description": "A tag/keyword that this package relates to."
49016             }
49017         },
49018         "homepage": {
49019             "type": "string",
49020             "description": "Homepage URL for the project.",
49021             "format": "uri"
49022         },
49023         "readme": {
49024             "type": "string",
49025             "description": "Relative path to the readme document."
49026         },
49027         "version": {
49028             "type": "string",
49029             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
49030             "pattern": "^v?\\d+(((\\.\\d+)?\\.\\d+)?\\.\\d+)?|^dev-"
49031         },
49032         "time": {
49033             "type": "string",
49034             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
49035         },
49036         "license": {
49037             "type": ["string", "array"],
49038             "description": "License name. Or an array of license names."
49039         },
49040         "authors": {
49041             "$ref": "#/definitions/authors"
49042         },
49043         "require": {
49044             "type": "object",
49045             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
49046             "additionalProperties": {
49047                 "type": "string"
49048             }
49049         },
49050         "replace": {
49051             "type": "object",
49052             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
49053             "additionalProperties": {
49054                 "type": "string"
49055             }
49056         },
49057         "conflict": {
49058             "type": "object",
49059             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
49060             "additionalProperties": {
49061                 "type": "string"
49062             }
49063         },
49064         "provide": {
49065             "type": "object",
49066             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
49067             "additionalProperties": {
49068                 "type": "string"
49069             }
49070         },
49071         "require-dev": {
49072             "type": "object",
49073             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
49074             "additionalProperties": {
49075                 "type": "string"
49076             }
49077         },
49078         "suggest": {
49079             "type": "object",
49080             "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).",
49081             "additionalProperties": {
49082                 "type": "string"
49083             }
49084         },
49085         "config": {
49086             "type": "object",
49087             "description": "Composer options.",
49088             "properties": {
49089                 "process-timeout": {
49090                     "type": "integer",
49091                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
49092                 },
49093                 "use-include-path": {
49094                     "type": "boolean",
49095                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
49096                 },
49097                 "preferred-install": {
49098                     "type": ["string", "object"],
49099                     "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\"}."
49100                 },
49101                 "notify-on-install": {
49102                     "type": "boolean",
49103                     "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."
49104                 },
49105                 "github-protocols": {
49106                     "type": "array",
49107                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
49108                     "items": {
49109                         "type": "string"
49110                     }
49111                 },
49112                 "github-oauth": {
49113                     "type": "object",
49114                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
49115                     "additionalProperties": {
49116                         "type": "string"
49117                     }
49118                 },
49119                 "gitlab-oauth": {
49120                     "type": "object",
49121                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
49122                     "additionalProperties": {
49123                         "type": "string"
49124                     }
49125                 },
49126                 "gitlab-token": {
49127                     "type": "object",
49128                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
49129                     "additionalProperties": {
49130                         "type": "string"
49131                     }
49132                 },
49133                 "bearer": {
49134                     "type": "object",
49135                     "description": "A hash of domain name => bearer authentication token, for example {\"example.com\":\"<token>\"}.",
49136                     "additionalProperties": {
49137                         "type": "string"
49138                     }
49139                 },
49140                 "disable-tls": {
49141                     "type": "boolean",
49142                     "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."
49143                 },
49144                 "secure-http": {
49145                     "type": "boolean",
49146                     "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."
49147                 },
49148                 "cafile": {
49149                     "type": "string",
49150                     "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."
49151                 },
49152                 "capath": {
49153                     "type": "string",
49154                     "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."
49155                 },
49156                 "http-basic": {
49157                     "type": "object",
49158                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
49159                     "additionalProperties": {
49160                         "type": "object",
49161                         "required": ["username", "password"],
49162                         "properties": {
49163                             "username": {
49164                                 "type": "string",
49165                                 "description": "The username used for HTTP Basic authentication"
49166                             },
49167                             "password": {
49168                                 "type": "string",
49169                                 "description": "The password used for HTTP Basic authentication"
49170                             }
49171                         }
49172                     }
49173                 },
49174                 "store-auths": {
49175                     "type": ["string", "boolean"],
49176                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
49177                 },
49178                 "platform": {
49179                     "type": "object",
49180                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
49181                     "additionalProperties": {
49182                         "type": "string"
49183                     }
49184                 },
49185                 "vendor-dir": {
49186                     "type": "string",
49187                     "description": "The location where all packages are installed, defaults to \"vendor\"."
49188                 },
49189                 "bin-dir": {
49190                     "type": "string",
49191                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
49192                 },
49193                 "data-dir": {
49194                     "type": "string",
49195                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
49196                 },
49197                 "cache-dir": {
49198                     "type": "string",
49199                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
49200                 },
49201                 "cache-files-dir": {
49202                     "type": "string",
49203                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
49204                 },
49205                 "cache-repo-dir": {
49206                     "type": "string",
49207                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
49208                 },
49209                 "cache-vcs-dir": {
49210                     "type": "string",
49211                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
49212                 },
49213                 "cache-ttl": {
49214                     "type": "integer",
49215                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
49216                 },
49217                 "cache-files-ttl": {
49218                     "type": "integer",
49219                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
49220                 },
49221                 "cache-files-maxsize": {
49222                     "type": ["string", "integer"],
49223                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
49224                 },
49225                 "bin-compat": {
49226                     "enum": ["auto", "full"],
49227                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
49228                 },
49229                 "discard-changes": {
49230                     "type": ["string", "boolean"],
49231                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
49232                 },
49233                 "autoloader-suffix": {
49234                     "type": "string",
49235                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
49236                 },
49237                 "optimize-autoloader": {
49238                     "type": "boolean",
49239                     "description": "Always optimize when dumping the autoloader."
49240                 },
49241                 "prepend-autoloader": {
49242                     "type": "boolean",
49243                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
49244                 },
49245                 "classmap-authoritative": {
49246                     "type": "boolean",
49247                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
49248                 },
49249                 "apcu-autoloader": {
49250                     "type": "boolean",
49251                     "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."
49252                 },
49253                 "github-domains": {
49254                     "type": "array",
49255                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
49256                     "items": {
49257                         "type": "string"
49258                     }
49259                 },
49260                 "github-expose-hostname": {
49261                     "type": "boolean",
49262                     "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."
49263                 },
49264                 "gitlab-domains": {
49265                     "type": "array",
49266                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
49267                     "items": {
49268                         "type": "string"
49269                     }
49270                 },
49271                 "use-github-api": {
49272                     "type": "boolean",
49273                     "description": "Defaults to true.  If set to false, globally disables the use of the GitHub API for all GitHub repositories and clones the repository as it would for any other repository."
49274                 },
49275                 "archive-format": {
49276                     "type": "string",
49277                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
49278                 },
49279                 "archive-dir": {
49280                     "type": "string",
49281                     "description": "The default archive path when not provided on cli, defaults to \".\"."
49282                 },
49283                 "htaccess-protect": {
49284                     "type": "boolean",
49285                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
49286                 },
49287                 "sort-packages": {
49288                     "type": "boolean",
49289                     "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
49290                 },
49291                 "lock": {
49292                     "type": "boolean",
49293                     "description": "Defaults to true. If set to false, Composer will not create a composer.lock file."
49294                 }
49295             }
49296         },
49297         "extra": {
49298             "type": ["object", "array"],
49299             "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.",
49300             "additionalProperties": true
49301         },
49302         "autoload": {
49303             "$ref": "#/definitions/autoload"
49304         },
49305         "autoload-dev": {
49306             "type": "object",
49307             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
49308             "properties": {
49309                 "psr-0": {
49310                     "type": "object",
49311                     "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.",
49312                     "additionalProperties": {
49313                         "type": ["string", "array"],
49314                         "items": {
49315                             "type": "string"
49316                         }
49317                     }
49318                 },
49319                 "psr-4": {
49320                     "type": "object",
49321                     "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.",
49322                     "additionalProperties": {
49323                         "type": ["string", "array"],
49324                         "items": {
49325                             "type": "string"
49326                         }
49327                     }
49328                 },
49329                 "classmap": {
49330                     "type": "array",
49331                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
49332                 },
49333                 "files": {
49334                     "type": "array",
49335                     "description": "This is an array of files that are always required on every request."
49336                 }
49337             }
49338         },
49339         "archive": {
49340             "type": ["object"],
49341             "description": "Options for creating package archives for distribution.",
49342             "properties": {
49343                 "exclude": {
49344                     "type": "array",
49345                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
49346                 }
49347             }
49348         },
49349         "repositories": {
49350             "type": ["object", "array"],
49351             "description": "A set of additional repositories where packages can be found.",
49352             "additionalProperties": {
49353                 "anyOf": [
49354                     { "$ref": "#/definitions/repository" },
49355                     { "type": "boolean", "enum": [false] }
49356                 ]
49357             },
49358             "items": {
49359                 "anyOf": [
49360                     { "$ref": "#/definitions/repository" },
49361                     {
49362                         "type": "object",
49363                         "additionalProperties": { "type": "boolean", "enum": [false] },
49364                         "minProperties": 1,
49365                         "maxProperties": 1
49366                     }
49367                 ]
49368             }
49369         },
49370         "minimum-stability": {
49371             "type": ["string"],
49372             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
49373             "pattern": "^dev|alpha|beta|rc|RC|stable$"
49374         },
49375         "prefer-stable": {
49376             "type": ["boolean"],
49377             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
49378         },
49379         "bin": {
49380             "type": ["string", "array"],
49381             "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
49382             "items": {
49383                 "type": "string"
49384             }
49385         },
49386         "include-path": {
49387             "type": ["array"],
49388             "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.",
49389             "items": {
49390                 "type": "string"
49391             }
49392         },
49393         "scripts": {
49394             "type": ["object"],
49395             "description": "Script listeners that will be executed before/after some events.",
49396             "properties": {
49397                 "pre-install-cmd": {
49398                     "type": ["array", "string"],
49399                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
49400                 },
49401                 "post-install-cmd": {
49402                     "type": ["array", "string"],
49403                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
49404                 },
49405                 "pre-update-cmd": {
49406                     "type": ["array", "string"],
49407                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
49408                 },
49409                 "post-update-cmd": {
49410                     "type": ["array", "string"],
49411                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
49412                 },
49413                 "pre-status-cmd": {
49414                     "type": ["array", "string"],
49415                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
49416                 },
49417                 "post-status-cmd": {
49418                     "type": ["array", "string"],
49419                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
49420                 },
49421                 "pre-package-install": {
49422                     "type": ["array", "string"],
49423                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
49424                 },
49425                 "post-package-install": {
49426                     "type": ["array", "string"],
49427                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
49428                 },
49429                 "pre-package-update": {
49430                     "type": ["array", "string"],
49431                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
49432                 },
49433                 "post-package-update": {
49434                     "type": ["array", "string"],
49435                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
49436                 },
49437                 "pre-package-uninstall": {
49438                     "type": ["array", "string"],
49439                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
49440                 },
49441                 "post-package-uninstall": {
49442                     "type": ["array", "string"],
49443                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
49444                 },
49445                 "pre-autoload-dump": {
49446                     "type": ["array", "string"],
49447                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
49448                 },
49449                 "post-autoload-dump": {
49450                     "type": ["array", "string"],
49451                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
49452                 },
49453                 "post-root-package-install": {
49454                     "type": ["array", "string"],
49455                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
49456                 },
49457                 "post-create-project-cmd": {
49458                     "type": ["array", "string"],
49459                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
49460                 }
49461             }
49462         },
49463         "scripts-descriptions": {
49464             "type": ["object"],
49465             "description": "Descriptions for custom commands, shown in console help.",
49466             "additionalProperties": {
49467                 "type": "string"
49468             }
49469         },
49470         "support": {
49471             "type": "object",
49472             "properties": {
49473                 "email": {
49474                     "type": "string",
49475                     "description": "Email address for support.",
49476                     "format": "email"
49477                 },
49478                 "issues": {
49479                     "type": "string",
49480                     "description": "URL to the issue tracker.",
49481                     "format": "uri"
49482                 },
49483                 "forum": {
49484                     "type": "string",
49485                     "description": "URL to the forum.",
49486                     "format": "uri"
49487                 },
49488                 "wiki": {
49489                     "type": "string",
49490                     "description": "URL to the wiki.",
49491                     "format": "uri"
49492                 },
49493                 "irc": {
49494                     "type": "string",
49495                     "description": "IRC channel for support, as irc://server/channel.",
49496                     "format": "uri"
49497                 },
49498                 "chat": {
49499                     "type": "string",
49500                     "description": "URL to the support chat.",
49501                     "format": "uri"
49502                 },
49503                 "source": {
49504                     "type": "string",
49505                     "description": "URL to browse or download the sources.",
49506                     "format": "uri"
49507                 },
49508                 "docs": {
49509                     "type": "string",
49510                     "description": "URL to the documentation.",
49511                     "format": "uri"
49512                 },
49513                 "rss": {
49514                     "type": "string",
49515                     "description": "URL to the RSS feed.",
49516                     "format": "uri"
49517                 }
49518             }
49519         },
49520         "funding": {
49521             "type": "array",
49522             "description": "A list of options to fund the development and maintenance of the package.",
49523             "items": {
49524                 "type": "object",
49525                 "properties": {
49526                     "type": {
49527                         "type": "string",
49528                         "description": "Type of funding or platform through which funding is possible."
49529                     },
49530                     "url": {
49531                         "type": "string",
49532                         "description": "URL to a website with details on funding and a way to fund the package.",
49533                         "format": "uri"
49534                     }
49535                 }
49536             }
49537         },
49538         "non-feature-branches": {
49539             "type": ["array"],
49540             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
49541             "items": {
49542                 "type": "string"
49543             }
49544         },
49545         "abandoned": {
49546             "type": ["boolean", "string"],
49547             "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."
49548         },
49549         "_comment": {
49550             "type": ["array", "string"],
49551             "description": "A key to store comments in"
49552         }
49553     },
49554     "definitions": {
49555         "authors": {
49556             "type": "array",
49557             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
49558             "items": {
49559                 "type": "object",
49560                 "additionalProperties": false,
49561                 "required": [ "name"],
49562                 "properties": {
49563                     "name": {
49564                         "type": "string",
49565                         "description": "Full name of the author."
49566                     },
49567                     "email": {
49568                         "type": "string",
49569                         "description": "Email address of the author.",
49570                         "format": "email"
49571                     },
49572                     "homepage": {
49573                         "type": "string",
49574                         "description": "Homepage URL for the author.",
49575                         "format": "uri"
49576                     },
49577                     "role": {
49578                         "type": "string",
49579                         "description": "Author's role in the project."
49580                     }
49581                 }
49582             }
49583         },
49584         "autoload": {
49585             "type": "object",
49586             "description": "Description of how the package can be autoloaded.",
49587             "properties": {
49588                 "psr-0": {
49589                     "type": "object",
49590                     "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.",
49591                     "additionalProperties": {
49592                         "type": ["string", "array"],
49593                         "items": {
49594                             "type": "string"
49595                         }
49596                     }
49597                 },
49598                 "psr-4": {
49599                     "type": "object",
49600                     "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.",
49601                     "additionalProperties": {
49602                         "type": ["string", "array"],
49603                         "items": {
49604                             "type": "string"
49605                         }
49606                     }
49607                 },
49608                 "classmap": {
49609                     "type": "array",
49610                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
49611                 },
49612                 "files": {
49613                     "type": "array",
49614                     "description": "This is an array of files that are always required on every request."
49615                 },
49616                 "exclude-from-classmap": {
49617                     "type": "array",
49618                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
49619                 }
49620             }
49621         },
49622         "repository": {
49623             "type": "object",
49624             "anyOf": [
49625                 { "$ref": "#/definitions/composer-repository" },
49626                 { "$ref": "#/definitions/vcs-repository" },
49627                 { "$ref": "#/definitions/path-repository" },
49628                 { "$ref": "#/definitions/artifact-repository" },
49629                 { "$ref": "#/definitions/pear-repository" },
49630                 { "$ref": "#/definitions/package-repository" }
49631             ]
49632         },
49633         "composer-repository": {
49634             "type": "object",
49635             "required": ["type", "url"],
49636             "properties": {
49637                 "type": { "type": "string", "enum": ["composer"] },
49638                 "url": { "type": "string" },
49639                 "options": {
49640                     "type": "object",
49641                     "additionalProperties": true
49642                 },
49643                 "allow_ssl_downgrade": { "type": "boolean" },
49644                 "force-lazy-providers": { "type": "boolean" }
49645             }
49646         },
49647         "vcs-repository": {
49648             "type": "object",
49649             "required": ["type", "url"],
49650             "properties": {
49651                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
49652                 "url": { "type": "string" },
49653                 "no-api": { "type": "boolean" },
49654                 "secure-http": { "type": "boolean" },
49655                 "svn-cache-credentials": { "type": "boolean" },
49656                 "trunk-path": { "type": ["string", "boolean"] },
49657                 "branches-path": { "type": ["string", "boolean"] },
49658                 "tags-path": { "type": ["string", "boolean"] },
49659                 "package-path": { "type": "string" },
49660                 "depot": { "type": "string" },
49661                 "branch": { "type": "string" },
49662                 "unique_perforce_client_name": { "type": "string" },
49663                 "p4user": { "type": "string" },
49664                 "p4password": { "type": "string" }
49665             }
49666         },
49667         "path-repository": {
49668             "type": "object",
49669             "required": ["type", "url"],
49670             "properties": {
49671                 "type": { "type": "string", "enum": ["path"] },
49672                 "url": { "type": "string" },
49673                 "options": {
49674                     "type": "object",
49675                     "properties": {
49676                         "symlink": { "type": ["boolean", "null"] }
49677                     },
49678                     "additionalProperties": true
49679                 }
49680             }
49681         },
49682         "artifact-repository": {
49683             "type": "object",
49684             "required": ["type", "url"],
49685             "properties": {
49686                 "type": { "type": "string", "enum": ["artifact"] },
49687                 "url": { "type": "string" }
49688             }
49689         },
49690         "pear-repository": {
49691             "type": "object",
49692             "required": ["type", "url"],
49693             "properties": {
49694                 "type": { "type": "string", "enum": ["pear"] },
49695                 "url": { "type": "string" },
49696                 "vendor-alias": { "type": "string" }
49697             }
49698         },
49699         "package-repository": {
49700             "type": "object",
49701             "required": ["type", "package"],
49702             "properties": {
49703                 "type": { "type": "string", "enum": ["package"] },
49704                 "package": {
49705                     "oneOf": [
49706                         { "$ref": "#/definitions/inline-package" },
49707                         {
49708                             "type": "array",
49709                             "items": { "$ref": "#/definitions/inline-package" }
49710                         }
49711                     ]
49712                 }
49713             }
49714         },
49715         "inline-package": {
49716             "type": "object",
49717             "required": ["name", "version"],
49718             "properties": {
49719                 "name": {
49720                     "type": "string",
49721                     "description": "Package name, including 'vendor-name/' prefix."
49722                 },
49723                 "type": {
49724                     "type": "string"
49725                 },
49726                 "target-dir": {
49727                     "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.",
49728                     "type": "string"
49729                 },
49730                 "description": {
49731                     "type": "string"
49732                 },
49733                 "keywords": {
49734                     "type": "array",
49735                     "items": {
49736                         "type": "string"
49737                     }
49738                 },
49739                 "homepage": {
49740                     "type": "string",
49741                     "format": "uri"
49742                 },
49743                 "version": {
49744                     "type": "string"
49745                 },
49746                 "time": {
49747                     "type": "string"
49748                 },
49749                 "license": {
49750                     "type": [
49751                         "string",
49752                         "array"
49753                     ]
49754                 },
49755                 "authors": {
49756                     "$ref": "#/definitions/authors"
49757                 },
49758                 "require": {
49759                     "type": "object",
49760                     "additionalProperties": {
49761                         "type": "string"
49762                     }
49763                 },
49764                 "replace": {
49765                     "type": "object",
49766                     "additionalProperties": {
49767                         "type": "string"
49768                     }
49769                 },
49770                 "conflict": {
49771                     "type": "object",
49772                     "additionalProperties": {
49773                         "type": "string"
49774                     }
49775                 },
49776                 "provide": {
49777                     "type": "object",
49778                     "additionalProperties": {
49779                         "type": "string"
49780                     }
49781                 },
49782                 "require-dev": {
49783                     "type": "object",
49784                     "additionalProperties": {
49785                         "type": "string"
49786                     }
49787                 },
49788                 "suggest": {
49789                     "type": "object",
49790                     "additionalProperties": {
49791                         "type": "string"
49792                     }
49793                 },
49794                 "extra": {
49795                     "type": ["object", "array"],
49796                     "additionalProperties": true
49797                 },
49798                 "autoload": {
49799                     "$ref": "#/definitions/autoload"
49800                 },
49801                 "archive": {
49802                     "type": ["object"],
49803                     "properties": {
49804                         "exclude": {
49805                             "type": "array"
49806                         }
49807                     }
49808                 },
49809                 "bin": {
49810                     "type": ["string", "array"],
49811                     "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
49812                     "items": {
49813                         "type": "string"
49814                     }
49815                 },
49816                 "include-path": {
49817                     "type": ["array"],
49818                     "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.",
49819                     "items": {
49820                         "type": "string"
49821                     }
49822                 },
49823                 "source": {
49824                     "type": "object",
49825                     "required": ["type", "url", "reference"],
49826                     "properties": {
49827                         "type": {
49828                             "type": "string"
49829                         },
49830                         "url": {
49831                             "type": "string"
49832                         },
49833                         "reference": {
49834                             "type": "string"
49835                         },
49836                         "mirrors": {
49837                             "type": "array"
49838                         }
49839                     }
49840                 },
49841                 "dist": {
49842                     "type": "object",
49843                     "required": ["type", "url"],
49844                     "properties": {
49845                         "type": {
49846                             "type": "string"
49847                         },
49848                         "url": {
49849                             "type": "string"
49850                         },
49851                         "reference": {
49852                             "type": "string"
49853                         },
49854                         "shasum": {
49855                             "type": "string"
49856                         },
49857                         "mirrors": {
49858                             "type": "array"
49859                         }
49860                     }
49861                 }
49862             },
49863             "additionalProperties": true
49864         }
49865     }
49866 }
49867 {
49868     "389-exception": [
49869         "389 Directory Server Exception"
49870     ],
49871     "Autoconf-exception-2.0": [
49872         "Autoconf exception 2.0"
49873     ],
49874     "Autoconf-exception-3.0": [
49875         "Autoconf exception 3.0"
49876     ],
49877     "Bison-exception-2.2": [
49878         "Bison exception 2.2"
49879     ],
49880     "Bootloader-exception": [
49881         "Bootloader Distribution Exception"
49882     ],
49883     "Classpath-exception-2.0": [
49884         "Classpath exception 2.0"
49885     ],
49886     "CLISP-exception-2.0": [
49887         "CLISP exception 2.0"
49888     ],
49889     "DigiRule-FOSS-exception": [
49890         "DigiRule FOSS License Exception"
49891     ],
49892     "eCos-exception-2.0": [
49893         "eCos exception 2.0"
49894     ],
49895     "Fawkes-Runtime-exception": [
49896         "Fawkes Runtime Exception"
49897     ],
49898     "FLTK-exception": [
49899         "FLTK exception"
49900     ],
49901     "Font-exception-2.0": [
49902         "Font exception 2.0"
49903     ],
49904     "freertos-exception-2.0": [
49905         "FreeRTOS Exception 2.0"
49906     ],
49907     "GCC-exception-2.0": [
49908         "GCC Runtime Library exception 2.0"
49909     ],
49910     "GCC-exception-3.1": [
49911         "GCC Runtime Library exception 3.1"
49912     ],
49913     "gnu-javamail-exception": [
49914         "GNU JavaMail exception"
49915     ],
49916     "GPL-3.0-linking-exception": [
49917         "GPL-3.0 Linking Exception"
49918     ],
49919     "GPL-3.0-linking-source-exception": [
49920         "GPL-3.0 Linking Exception (with Corresponding Source)"
49921     ],
49922     "GPL-CC-1.0": [
49923         "GPL Cooperation Commitment 1.0"
49924     ],
49925     "i2p-gpl-java-exception": [
49926         "i2p GPL+Java Exception"
49927     ],
49928     "LGPL-3.0-linking-exception": [
49929         "LGPL-3.0 Linking Exception"
49930     ],
49931     "Libtool-exception": [
49932         "Libtool Exception"
49933     ],
49934     "Linux-syscall-note": [
49935         "Linux Syscall Note"
49936     ],
49937     "LLVM-exception": [
49938         "LLVM Exception"
49939     ],
49940     "LZMA-exception": [
49941         "LZMA exception"
49942     ],
49943     "mif-exception": [
49944         "Macros and Inline Functions Exception"
49945     ],
49946     "Nokia-Qt-exception-1.1": [
49947         "Nokia Qt LGPL exception 1.1"
49948     ],
49949     "OCaml-LGPL-linking-exception": [
49950         "OCaml LGPL Linking Exception"
49951     ],
49952     "OCCT-exception-1.0": [
49953         "Open CASCADE Exception 1.0"
49954     ],
49955     "OpenJDK-assembly-exception-1.0": [
49956         "OpenJDK Assembly exception 1.0"
49957     ],
49958     "openvpn-openssl-exception": [
49959         "OpenVPN OpenSSL Exception"
49960     ],
49961     "PS-or-PDF-font-exception-20170817": [
49962         "PS/PDF font exception (2017-08-17)"
49963     ],
49964     "Qt-GPL-exception-1.0": [
49965         "Qt GPL exception 1.0"
49966     ],
49967     "Qt-LGPL-exception-1.1": [
49968         "Qt LGPL exception 1.1"
49969     ],
49970     "Qwt-exception-1.0": [
49971         "Qwt exception 1.0"
49972     ],
49973     "SHL-2.0": [
49974         "Solderpad Hardware License v2.0"
49975     ],
49976     "SHL-2.1": [
49977         "Solderpad Hardware License v2.1"
49978     ],
49979     "Swift-exception": [
49980         "Swift Exception"
49981     ],
49982     "u-boot-exception-2.0": [
49983         "U-Boot exception 2.0"
49984     ],
49985     "Universal-FOSS-exception-1.0": [
49986         "Universal FOSS Exception, Version 1.0"
49987     ],
49988     "WxWindows-exception-3.1": [
49989         "WxWindows Library Exception 3.1"
49990     ]
49991 }{
49992     "0BSD": [
49993         "BSD Zero Clause License",
49994         true,
49995         false
49996     ],
49997     "AAL": [
49998         "Attribution Assurance License",
49999         true,
50000         false
50001     ],
50002     "Abstyles": [
50003         "Abstyles License",
50004         false,
50005         false
50006     ],
50007     "Adobe-2006": [
50008         "Adobe Systems Incorporated Source Code License Agreement",
50009         false,
50010         false
50011     ],
50012     "Adobe-Glyph": [
50013         "Adobe Glyph List License",
50014         false,
50015         false
50016     ],
50017     "ADSL": [
50018         "Amazon Digital Services License",
50019         false,
50020         false
50021     ],
50022     "AFL-1.1": [
50023         "Academic Free License v1.1",
50024         true,
50025         false
50026     ],
50027     "AFL-1.2": [
50028         "Academic Free License v1.2",
50029         true,
50030         false
50031     ],
50032     "AFL-2.0": [
50033         "Academic Free License v2.0",
50034         true,
50035         false
50036     ],
50037     "AFL-2.1": [
50038         "Academic Free License v2.1",
50039         true,
50040         false
50041     ],
50042     "AFL-3.0": [
50043         "Academic Free License v3.0",
50044         true,
50045         false
50046     ],
50047     "Afmparse": [
50048         "Afmparse License",
50049         false,
50050         false
50051     ],
50052     "AGPL-1.0": [
50053         "Affero General Public License v1.0",
50054         false,
50055         true
50056     ],
50057     "AGPL-1.0-only": [
50058         "Affero General Public License v1.0 only",
50059         false,
50060         false
50061     ],
50062     "AGPL-1.0-or-later": [
50063         "Affero General Public License v1.0 or later",
50064         false,
50065         false
50066     ],
50067     "AGPL-3.0": [
50068         "GNU Affero General Public License v3.0",
50069         true,
50070         true
50071     ],
50072     "AGPL-3.0-only": [
50073         "GNU Affero General Public License v3.0 only",
50074         true,
50075         false
50076     ],
50077     "AGPL-3.0-or-later": [
50078         "GNU Affero General Public License v3.0 or later",
50079         true,
50080         false
50081     ],
50082     "Aladdin": [
50083         "Aladdin Free Public License",
50084         false,
50085         false
50086     ],
50087     "AMDPLPA": [
50088         "AMD's plpa_map.c License",
50089         false,
50090         false
50091     ],
50092     "AML": [
50093         "Apple MIT License",
50094         false,
50095         false
50096     ],
50097     "AMPAS": [
50098         "Academy of Motion Picture Arts and Sciences BSD",
50099         false,
50100         false
50101     ],
50102     "ANTLR-PD": [
50103         "ANTLR Software Rights Notice",
50104         false,
50105         false
50106     ],
50107     "ANTLR-PD-fallback": [
50108         "ANTLR Software Rights Notice with license fallback",
50109         false,
50110         false
50111     ],
50112     "Apache-1.0": [
50113         "Apache License 1.0",
50114         false,
50115         false
50116     ],
50117     "Apache-1.1": [
50118         "Apache License 1.1",
50119         true,
50120         false
50121     ],
50122     "Apache-2.0": [
50123         "Apache License 2.0",
50124         true,
50125         false
50126     ],
50127     "APAFML": [
50128         "Adobe Postscript AFM License",
50129         false,
50130         false
50131     ],
50132     "APL-1.0": [
50133         "Adaptive Public License 1.0",
50134         true,
50135         false
50136     ],
50137     "APSL-1.0": [
50138         "Apple Public Source License 1.0",
50139         true,
50140         false
50141     ],
50142     "APSL-1.1": [
50143         "Apple Public Source License 1.1",
50144         true,
50145         false
50146     ],
50147     "APSL-1.2": [
50148         "Apple Public Source License 1.2",
50149         true,
50150         false
50151     ],
50152     "APSL-2.0": [
50153         "Apple Public Source License 2.0",
50154         true,
50155         false
50156     ],
50157     "Artistic-1.0": [
50158         "Artistic License 1.0",
50159         true,
50160         false
50161     ],
50162     "Artistic-1.0-cl8": [
50163         "Artistic License 1.0 w/clause 8",
50164         true,
50165         false
50166     ],
50167     "Artistic-1.0-Perl": [
50168         "Artistic License 1.0 (Perl)",
50169         true,
50170         false
50171     ],
50172     "Artistic-2.0": [
50173         "Artistic License 2.0",
50174         true,
50175         false
50176     ],
50177     "Bahyph": [
50178         "Bahyph License",
50179         false,
50180         false
50181     ],
50182     "Barr": [
50183         "Barr License",
50184         false,
50185         false
50186     ],
50187     "Beerware": [
50188         "Beerware License",
50189         false,
50190         false
50191     ],
50192     "BitTorrent-1.0": [
50193         "BitTorrent Open Source License v1.0",
50194         false,
50195         false
50196     ],
50197     "BitTorrent-1.1": [
50198         "BitTorrent Open Source License v1.1",
50199         false,
50200         false
50201     ],
50202     "blessing": [
50203         "SQLite Blessing",
50204         false,
50205         false
50206     ],
50207     "BlueOak-1.0.0": [
50208         "Blue Oak Model License 1.0.0",
50209         false,
50210         false
50211     ],
50212     "Borceux": [
50213         "Borceux license",
50214         false,
50215         false
50216     ],
50217     "BSD-1-Clause": [
50218         "BSD 1-Clause License",
50219         true,
50220         false
50221     ],
50222     "BSD-2-Clause": [
50223         "BSD 2-Clause \"Simplified\" License",
50224         true,
50225         false
50226     ],
50227     "BSD-2-Clause-FreeBSD": [
50228         "BSD 2-Clause FreeBSD License",
50229         false,
50230         true
50231     ],
50232     "BSD-2-Clause-NetBSD": [
50233         "BSD 2-Clause NetBSD License",
50234         false,
50235         true
50236     ],
50237     "BSD-2-Clause-Patent": [
50238         "BSD-2-Clause Plus Patent License",
50239         true,
50240         false
50241     ],
50242     "BSD-2-Clause-Views": [
50243         "BSD 2-Clause with views sentence",
50244         false,
50245         false
50246     ],
50247     "BSD-3-Clause": [
50248         "BSD 3-Clause \"New\" or \"Revised\" License",
50249         true,
50250         false
50251     ],
50252     "BSD-3-Clause-Attribution": [
50253         "BSD with attribution",
50254         false,
50255         false
50256     ],
50257     "BSD-3-Clause-Clear": [
50258         "BSD 3-Clause Clear License",
50259         false,
50260         false
50261     ],
50262     "BSD-3-Clause-LBNL": [
50263         "Lawrence Berkeley National Labs BSD variant license",
50264         true,
50265         false
50266     ],
50267     "BSD-3-Clause-Modification": [
50268         "BSD 3-Clause Modification",
50269         false,
50270         false
50271     ],
50272     "BSD-3-Clause-No-Military-License": [
50273         "BSD 3-Clause No Military License",
50274         false,
50275         false
50276     ],
50277     "BSD-3-Clause-No-Nuclear-License": [
50278         "BSD 3-Clause No Nuclear License",
50279         false,
50280         false
50281     ],
50282     "BSD-3-Clause-No-Nuclear-License-2014": [
50283         "BSD 3-Clause No Nuclear License 2014",
50284         false,
50285         false
50286     ],
50287     "BSD-3-Clause-No-Nuclear-Warranty": [
50288         "BSD 3-Clause No Nuclear Warranty",
50289         false,
50290         false
50291     ],
50292     "BSD-3-Clause-Open-MPI": [
50293         "BSD 3-Clause Open MPI variant",
50294         false,
50295         false
50296     ],
50297     "BSD-4-Clause": [
50298         "BSD 4-Clause \"Original\" or \"Old\" License",
50299         false,
50300         false
50301     ],
50302     "BSD-4-Clause-Shortened": [
50303         "BSD 4 Clause Shortened",
50304         false,
50305         false
50306     ],
50307     "BSD-4-Clause-UC": [
50308         "BSD-4-Clause (University of California-Specific)",
50309         false,
50310         false
50311     ],
50312     "BSD-Protection": [
50313         "BSD Protection License",
50314         false,
50315         false
50316     ],
50317     "BSD-Source-Code": [
50318         "BSD Source Code Attribution",
50319         false,
50320         false
50321     ],
50322     "BSL-1.0": [
50323         "Boost Software License 1.0",
50324         true,
50325         false
50326     ],
50327     "BUSL-1.1": [
50328         "Business Source License 1.1",
50329         false,
50330         false
50331     ],
50332     "bzip2-1.0.5": [
50333         "bzip2 and libbzip2 License v1.0.5",
50334         false,
50335         false
50336     ],
50337     "bzip2-1.0.6": [
50338         "bzip2 and libbzip2 License v1.0.6",
50339         false,
50340         false
50341     ],
50342     "C-UDA-1.0": [
50343         "Computational Use of Data Agreement v1.0",
50344         false,
50345         false
50346     ],
50347     "CAL-1.0": [
50348         "Cryptographic Autonomy License 1.0",
50349         true,
50350         false
50351     ],
50352     "CAL-1.0-Combined-Work-Exception": [
50353         "Cryptographic Autonomy License 1.0 (Combined Work Exception)",
50354         true,
50355         false
50356     ],
50357     "Caldera": [
50358         "Caldera License",
50359         false,
50360         false
50361     ],
50362     "CATOSL-1.1": [
50363         "Computer Associates Trusted Open Source License 1.1",
50364         true,
50365         false
50366     ],
50367     "CC-BY-1.0": [
50368         "Creative Commons Attribution 1.0 Generic",
50369         false,
50370         false
50371     ],
50372     "CC-BY-2.0": [
50373         "Creative Commons Attribution 2.0 Generic",
50374         false,
50375         false
50376     ],
50377     "CC-BY-2.5": [
50378         "Creative Commons Attribution 2.5 Generic",
50379         false,
50380         false
50381     ],
50382     "CC-BY-2.5-AU": [
50383         "Creative Commons Attribution 2.5 Australia",
50384         false,
50385         false
50386     ],
50387     "CC-BY-3.0": [
50388         "Creative Commons Attribution 3.0 Unported",
50389         false,
50390         false
50391     ],
50392     "CC-BY-3.0-AT": [
50393         "Creative Commons Attribution 3.0 Austria",
50394         false,
50395         false
50396     ],
50397     "CC-BY-3.0-DE": [
50398         "Creative Commons Attribution 3.0 Germany",
50399         false,
50400         false
50401     ],
50402     "CC-BY-3.0-NL": [
50403         "Creative Commons Attribution 3.0 Netherlands",
50404         false,
50405         false
50406     ],
50407     "CC-BY-3.0-US": [
50408         "Creative Commons Attribution 3.0 United States",
50409         false,
50410         false
50411     ],
50412     "CC-BY-4.0": [
50413         "Creative Commons Attribution 4.0 International",
50414         false,
50415         false
50416     ],
50417     "CC-BY-NC-1.0": [
50418         "Creative Commons Attribution Non Commercial 1.0 Generic",
50419         false,
50420         false
50421     ],
50422     "CC-BY-NC-2.0": [
50423         "Creative Commons Attribution Non Commercial 2.0 Generic",
50424         false,
50425         false
50426     ],
50427     "CC-BY-NC-2.5": [
50428         "Creative Commons Attribution Non Commercial 2.5 Generic",
50429         false,
50430         false
50431     ],
50432     "CC-BY-NC-3.0": [
50433         "Creative Commons Attribution Non Commercial 3.0 Unported",
50434         false,
50435         false
50436     ],
50437     "CC-BY-NC-3.0-DE": [
50438         "Creative Commons Attribution Non Commercial 3.0 Germany",
50439         false,
50440         false
50441     ],
50442     "CC-BY-NC-4.0": [
50443         "Creative Commons Attribution Non Commercial 4.0 International",
50444         false,
50445         false
50446     ],
50447     "CC-BY-NC-ND-1.0": [
50448         "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",
50449         false,
50450         false
50451     ],
50452     "CC-BY-NC-ND-2.0": [
50453         "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",
50454         false,
50455         false
50456     ],
50457     "CC-BY-NC-ND-2.5": [
50458         "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",
50459         false,
50460         false
50461     ],
50462     "CC-BY-NC-ND-3.0": [
50463         "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",
50464         false,
50465         false
50466     ],
50467     "CC-BY-NC-ND-3.0-DE": [
50468         "Creative Commons Attribution Non Commercial No Derivatives 3.0 Germany",
50469         false,
50470         false
50471     ],
50472     "CC-BY-NC-ND-3.0-IGO": [
50473         "Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO",
50474         false,
50475         false
50476     ],
50477     "CC-BY-NC-ND-4.0": [
50478         "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",
50479         false,
50480         false
50481     ],
50482     "CC-BY-NC-SA-1.0": [
50483         "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",
50484         false,
50485         false
50486     ],
50487     "CC-BY-NC-SA-2.0": [
50488         "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",
50489         false,
50490         false
50491     ],
50492     "CC-BY-NC-SA-2.0-FR": [
50493         "Creative Commons Attribution-NonCommercial-ShareAlike 2.0 France",
50494         false,
50495         false
50496     ],
50497     "CC-BY-NC-SA-2.0-UK": [
50498         "Creative Commons Attribution Non Commercial Share Alike 2.0 England and Wales",
50499         false,
50500         false
50501     ],
50502     "CC-BY-NC-SA-2.5": [
50503         "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",
50504         false,
50505         false
50506     ],
50507     "CC-BY-NC-SA-3.0": [
50508         "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",
50509         false,
50510         false
50511     ],
50512     "CC-BY-NC-SA-3.0-DE": [
50513         "Creative Commons Attribution Non Commercial Share Alike 3.0 Germany",
50514         false,
50515         false
50516     ],
50517     "CC-BY-NC-SA-3.0-IGO": [
50518         "Creative Commons Attribution Non Commercial Share Alike 3.0 IGO",
50519         false,
50520         false
50521     ],
50522     "CC-BY-NC-SA-4.0": [
50523         "Creative Commons Attribution Non Commercial Share Alike 4.0 International",
50524         false,
50525         false
50526     ],
50527     "CC-BY-ND-1.0": [
50528         "Creative Commons Attribution No Derivatives 1.0 Generic",
50529         false,
50530         false
50531     ],
50532     "CC-BY-ND-2.0": [
50533         "Creative Commons Attribution No Derivatives 2.0 Generic",
50534         false,
50535         false
50536     ],
50537     "CC-BY-ND-2.5": [
50538         "Creative Commons Attribution No Derivatives 2.5 Generic",
50539         false,
50540         false
50541     ],
50542     "CC-BY-ND-3.0": [
50543         "Creative Commons Attribution No Derivatives 3.0 Unported",
50544         false,
50545         false
50546     ],
50547     "CC-BY-ND-3.0-DE": [
50548         "Creative Commons Attribution No Derivatives 3.0 Germany",
50549         false,
50550         false
50551     ],
50552     "CC-BY-ND-4.0": [
50553         "Creative Commons Attribution No Derivatives 4.0 International",
50554         false,
50555         false
50556     ],
50557     "CC-BY-SA-1.0": [
50558         "Creative Commons Attribution Share Alike 1.0 Generic",
50559         false,
50560         false
50561     ],
50562     "CC-BY-SA-2.0": [
50563         "Creative Commons Attribution Share Alike 2.0 Generic",
50564         false,
50565         false
50566     ],
50567     "CC-BY-SA-2.0-UK": [
50568         "Creative Commons Attribution Share Alike 2.0 England and Wales",
50569         false,
50570         false
50571     ],
50572     "CC-BY-SA-2.1-JP": [
50573         "Creative Commons Attribution Share Alike 2.1 Japan",
50574         false,
50575         false
50576     ],
50577     "CC-BY-SA-2.5": [
50578         "Creative Commons Attribution Share Alike 2.5 Generic",
50579         false,
50580         false
50581     ],
50582     "CC-BY-SA-3.0": [
50583         "Creative Commons Attribution Share Alike 3.0 Unported",
50584         false,
50585         false
50586     ],
50587     "CC-BY-SA-3.0-AT": [
50588         "Creative Commons Attribution Share Alike 3.0 Austria",
50589         false,
50590         false
50591     ],
50592     "CC-BY-SA-3.0-DE": [
50593         "Creative Commons Attribution Share Alike 3.0 Germany",
50594         false,
50595         false
50596     ],
50597     "CC-BY-SA-4.0": [
50598         "Creative Commons Attribution Share Alike 4.0 International",
50599         false,
50600         false
50601     ],
50602     "CC-PDDC": [
50603         "Creative Commons Public Domain Dedication and Certification",
50604         false,
50605         false
50606     ],
50607     "CC0-1.0": [
50608         "Creative Commons Zero v1.0 Universal",
50609         false,
50610         false
50611     ],
50612     "CDDL-1.0": [
50613         "Common Development and Distribution License 1.0",
50614         true,
50615         false
50616     ],
50617     "CDDL-1.1": [
50618         "Common Development and Distribution License 1.1",
50619         false,
50620         false
50621     ],
50622     "CDL-1.0": [
50623         "Common Documentation License 1.0",
50624         false,
50625         false
50626     ],
50627     "CDLA-Permissive-1.0": [
50628         "Community Data License Agreement Permissive 1.0",
50629         false,
50630         false
50631     ],
50632     "CDLA-Permissive-2.0": [
50633         "Community Data License Agreement Permissive 2.0",
50634         false,
50635         false
50636     ],
50637     "CDLA-Sharing-1.0": [
50638         "Community Data License Agreement Sharing 1.0",
50639         false,
50640         false
50641     ],
50642     "CECILL-1.0": [
50643         "CeCILL Free Software License Agreement v1.0",
50644         false,
50645         false
50646     ],
50647     "CECILL-1.1": [
50648         "CeCILL Free Software License Agreement v1.1",
50649         false,
50650         false
50651     ],
50652     "CECILL-2.0": [
50653         "CeCILL Free Software License Agreement v2.0",
50654         false,
50655         false
50656     ],
50657     "CECILL-2.1": [
50658         "CeCILL Free Software License Agreement v2.1",
50659         true,
50660         false
50661     ],
50662     "CECILL-B": [
50663         "CeCILL-B Free Software License Agreement",
50664         false,
50665         false
50666     ],
50667     "CECILL-C": [
50668         "CeCILL-C Free Software License Agreement",
50669         false,
50670         false
50671     ],
50672     "CERN-OHL-1.1": [
50673         "CERN Open Hardware Licence v1.1",
50674         false,
50675         false
50676     ],
50677     "CERN-OHL-1.2": [
50678         "CERN Open Hardware Licence v1.2",
50679         false,
50680         false
50681     ],
50682     "CERN-OHL-P-2.0": [
50683         "CERN Open Hardware Licence Version 2 - Permissive",
50684         true,
50685         false
50686     ],
50687     "CERN-OHL-S-2.0": [
50688         "CERN Open Hardware Licence Version 2 - Strongly Reciprocal",
50689         true,
50690         false
50691     ],
50692     "CERN-OHL-W-2.0": [
50693         "CERN Open Hardware Licence Version 2 - Weakly Reciprocal",
50694         true,
50695         false
50696     ],
50697     "ClArtistic": [
50698         "Clarified Artistic License",
50699         false,
50700         false
50701     ],
50702     "CNRI-Jython": [
50703         "CNRI Jython License",
50704         false,
50705         false
50706     ],
50707     "CNRI-Python": [
50708         "CNRI Python License",
50709         true,
50710         false
50711     ],
50712     "CNRI-Python-GPL-Compatible": [
50713         "CNRI Python Open Source GPL Compatible License Agreement",
50714         false,
50715         false
50716     ],
50717     "COIL-1.0": [
50718         "Copyfree Open Innovation License",
50719         false,
50720         false
50721     ],
50722     "Community-Spec-1.0": [
50723         "Community Specification License 1.0",
50724         false,
50725         false
50726     ],
50727     "Condor-1.1": [
50728         "Condor Public License v1.1",
50729         false,
50730         false
50731     ],
50732     "copyleft-next-0.3.0": [
50733         "copyleft-next 0.3.0",
50734         false,
50735         false
50736     ],
50737     "copyleft-next-0.3.1": [
50738         "copyleft-next 0.3.1",
50739         false,
50740         false
50741     ],
50742     "CPAL-1.0": [
50743         "Common Public Attribution License 1.0",
50744         true,
50745         false
50746     ],
50747     "CPL-1.0": [
50748         "Common Public License 1.0",
50749         true,
50750         false
50751     ],
50752     "CPOL-1.02": [
50753         "Code Project Open License 1.02",
50754         false,
50755         false
50756     ],
50757     "Crossword": [
50758         "Crossword License",
50759         false,
50760         false
50761     ],
50762     "CrystalStacker": [
50763         "CrystalStacker License",
50764         false,
50765         false
50766     ],
50767     "CUA-OPL-1.0": [
50768         "CUA Office Public License v1.0",
50769         true,
50770         false
50771     ],
50772     "Cube": [
50773         "Cube License",
50774         false,
50775         false
50776     ],
50777     "curl": [
50778         "curl License",
50779         false,
50780         false
50781     ],
50782     "D-FSL-1.0": [
50783         "Deutsche Freie Software Lizenz",
50784         false,
50785         false
50786     ],
50787     "diffmark": [
50788         "diffmark license",
50789         false,
50790         false
50791     ],
50792     "DOC": [
50793         "DOC License",
50794         false,
50795         false
50796     ],
50797     "Dotseqn": [
50798         "Dotseqn License",
50799         false,
50800         false
50801     ],
50802     "DRL-1.0": [
50803         "Detection Rule License 1.0",
50804         false,
50805         false
50806     ],
50807     "DSDP": [
50808         "DSDP License",
50809         false,
50810         false
50811     ],
50812     "dvipdfm": [
50813         "dvipdfm License",
50814         false,
50815         false
50816     ],
50817     "ECL-1.0": [
50818         "Educational Community License v1.0",
50819         true,
50820         false
50821     ],
50822     "ECL-2.0": [
50823         "Educational Community License v2.0",
50824         true,
50825         false
50826     ],
50827     "eCos-2.0": [
50828         "eCos license version 2.0",
50829         false,
50830         true
50831     ],
50832     "EFL-1.0": [
50833         "Eiffel Forum License v1.0",
50834         true,
50835         false
50836     ],
50837     "EFL-2.0": [
50838         "Eiffel Forum License v2.0",
50839         true,
50840         false
50841     ],
50842     "eGenix": [
50843         "eGenix.com Public License 1.1.0",
50844         false,
50845         false
50846     ],
50847     "Entessa": [
50848         "Entessa Public License v1.0",
50849         true,
50850         false
50851     ],
50852     "EPICS": [
50853         "EPICS Open License",
50854         false,
50855         false
50856     ],
50857     "EPL-1.0": [
50858         "Eclipse Public License 1.0",
50859         true,
50860         false
50861     ],
50862     "EPL-2.0": [
50863         "Eclipse Public License 2.0",
50864         true,
50865         false
50866     ],
50867     "ErlPL-1.1": [
50868         "Erlang Public License v1.1",
50869         false,
50870         false
50871     ],
50872     "etalab-2.0": [
50873         "Etalab Open License 2.0",
50874         false,
50875         false
50876     ],
50877     "EUDatagrid": [
50878         "EU DataGrid Software License",
50879         true,
50880         false
50881     ],
50882     "EUPL-1.0": [
50883         "European Union Public License 1.0",
50884         false,
50885         false
50886     ],
50887     "EUPL-1.1": [
50888         "European Union Public License 1.1",
50889         true,
50890         false
50891     ],
50892     "EUPL-1.2": [
50893         "European Union Public License 1.2",
50894         true,
50895         false
50896     ],
50897     "Eurosym": [
50898         "Eurosym License",
50899         false,
50900         false
50901     ],
50902     "Fair": [
50903         "Fair License",
50904         true,
50905         false
50906     ],
50907     "FDK-AAC": [
50908         "Fraunhofer FDK AAC Codec Library",
50909         false,
50910         false
50911     ],
50912     "Frameworx-1.0": [
50913         "Frameworx Open License 1.0",
50914         true,
50915         false
50916     ],
50917     "FreeBSD-DOC": [
50918         "FreeBSD Documentation License",
50919         false,
50920         false
50921     ],
50922     "FreeImage": [
50923         "FreeImage Public License v1.0",
50924         false,
50925         false
50926     ],
50927     "FSFAP": [
50928         "FSF All Permissive License",
50929         false,
50930         false
50931     ],
50932     "FSFUL": [
50933         "FSF Unlimited License",
50934         false,
50935         false
50936     ],
50937     "FSFULLR": [
50938         "FSF Unlimited License (with License Retention)",
50939         false,
50940         false
50941     ],
50942     "FTL": [
50943         "Freetype Project License",
50944         false,
50945         false
50946     ],
50947     "GD": [
50948         "GD License",
50949         false,
50950         false
50951     ],
50952     "GFDL-1.1": [
50953         "GNU Free Documentation License v1.1",
50954         false,
50955         true
50956     ],
50957     "GFDL-1.1-invariants-only": [
50958         "GNU Free Documentation License v1.1 only - invariants",
50959         false,
50960         false
50961     ],
50962     "GFDL-1.1-invariants-or-later": [
50963         "GNU Free Documentation License v1.1 or later - invariants",
50964         false,
50965         false
50966     ],
50967     "GFDL-1.1-no-invariants-only": [
50968         "GNU Free Documentation License v1.1 only - no invariants",
50969         false,
50970         false
50971     ],
50972     "GFDL-1.1-no-invariants-or-later": [
50973         "GNU Free Documentation License v1.1 or later - no invariants",
50974         false,
50975         false
50976     ],
50977     "GFDL-1.1-only": [
50978         "GNU Free Documentation License v1.1 only",
50979         false,
50980         false
50981     ],
50982     "GFDL-1.1-or-later": [
50983         "GNU Free Documentation License v1.1 or later",
50984         false,
50985         false
50986     ],
50987     "GFDL-1.2": [
50988         "GNU Free Documentation License v1.2",
50989         false,
50990         true
50991     ],
50992     "GFDL-1.2-invariants-only": [
50993         "GNU Free Documentation License v1.2 only - invariants",
50994         false,
50995         false
50996     ],
50997     "GFDL-1.2-invariants-or-later": [
50998         "GNU Free Documentation License v1.2 or later - invariants",
50999         false,
51000         false
51001     ],
51002     "GFDL-1.2-no-invariants-only": [
51003         "GNU Free Documentation License v1.2 only - no invariants",
51004         false,
51005         false
51006     ],
51007     "GFDL-1.2-no-invariants-or-later": [
51008         "GNU Free Documentation License v1.2 or later - no invariants",
51009         false,
51010         false
51011     ],
51012     "GFDL-1.2-only": [
51013         "GNU Free Documentation License v1.2 only",
51014         false,
51015         false
51016     ],
51017     "GFDL-1.2-or-later": [
51018         "GNU Free Documentation License v1.2 or later",
51019         false,
51020         false
51021     ],
51022     "GFDL-1.3": [
51023         "GNU Free Documentation License v1.3",
51024         false,
51025         true
51026     ],
51027     "GFDL-1.3-invariants-only": [
51028         "GNU Free Documentation License v1.3 only - invariants",
51029         false,
51030         false
51031     ],
51032     "GFDL-1.3-invariants-or-later": [
51033         "GNU Free Documentation License v1.3 or later - invariants",
51034         false,
51035         false
51036     ],
51037     "GFDL-1.3-no-invariants-only": [
51038         "GNU Free Documentation License v1.3 only - no invariants",
51039         false,
51040         false
51041     ],
51042     "GFDL-1.3-no-invariants-or-later": [
51043         "GNU Free Documentation License v1.3 or later - no invariants",
51044         false,
51045         false
51046     ],
51047     "GFDL-1.3-only": [
51048         "GNU Free Documentation License v1.3 only",
51049         false,
51050         false
51051     ],
51052     "GFDL-1.3-or-later": [
51053         "GNU Free Documentation License v1.3 or later",
51054         false,
51055         false
51056     ],
51057     "Giftware": [
51058         "Giftware License",
51059         false,
51060         false
51061     ],
51062     "GL2PS": [
51063         "GL2PS License",
51064         false,
51065         false
51066     ],
51067     "Glide": [
51068         "3dfx Glide License",
51069         false,
51070         false
51071     ],
51072     "Glulxe": [
51073         "Glulxe License",
51074         false,
51075         false
51076     ],
51077     "GLWTPL": [
51078         "Good Luck With That Public License",
51079         false,
51080         false
51081     ],
51082     "gnuplot": [
51083         "gnuplot License",
51084         false,
51085         false
51086     ],
51087     "GPL-1.0": [
51088         "GNU General Public License v1.0 only",
51089         false,
51090         true
51091     ],
51092     "GPL-1.0+": [
51093         "GNU General Public License v1.0 or later",
51094         false,
51095         true
51096     ],
51097     "GPL-1.0-only": [
51098         "GNU General Public License v1.0 only",
51099         false,
51100         false
51101     ],
51102     "GPL-1.0-or-later": [
51103         "GNU General Public License v1.0 or later",
51104         false,
51105         false
51106     ],
51107     "GPL-2.0": [
51108         "GNU General Public License v2.0 only",
51109         true,
51110         true
51111     ],
51112     "GPL-2.0+": [
51113         "GNU General Public License v2.0 or later",
51114         true,
51115         true
51116     ],
51117     "GPL-2.0-only": [
51118         "GNU General Public License v2.0 only",
51119         true,
51120         false
51121     ],
51122     "GPL-2.0-or-later": [
51123         "GNU General Public License v2.0 or later",
51124         true,
51125         false
51126     ],
51127     "GPL-2.0-with-autoconf-exception": [
51128         "GNU General Public License v2.0 w/Autoconf exception",
51129         false,
51130         true
51131     ],
51132     "GPL-2.0-with-bison-exception": [
51133         "GNU General Public License v2.0 w/Bison exception",
51134         false,
51135         true
51136     ],
51137     "GPL-2.0-with-classpath-exception": [
51138         "GNU General Public License v2.0 w/Classpath exception",
51139         false,
51140         true
51141     ],
51142     "GPL-2.0-with-font-exception": [
51143         "GNU General Public License v2.0 w/Font exception",
51144         false,
51145         true
51146     ],
51147     "GPL-2.0-with-GCC-exception": [
51148         "GNU General Public License v2.0 w/GCC Runtime Library exception",
51149         false,
51150         true
51151     ],
51152     "GPL-3.0": [
51153         "GNU General Public License v3.0 only",
51154         true,
51155         true
51156     ],
51157     "GPL-3.0+": [
51158         "GNU General Public License v3.0 or later",
51159         true,
51160         true
51161     ],
51162     "GPL-3.0-only": [
51163         "GNU General Public License v3.0 only",
51164         true,
51165         false
51166     ],
51167     "GPL-3.0-or-later": [
51168         "GNU General Public License v3.0 or later",
51169         true,
51170         false
51171     ],
51172     "GPL-3.0-with-autoconf-exception": [
51173         "GNU General Public License v3.0 w/Autoconf exception",
51174         false,
51175         true
51176     ],
51177     "GPL-3.0-with-GCC-exception": [
51178         "GNU General Public License v3.0 w/GCC Runtime Library exception",
51179         true,
51180         true
51181     ],
51182     "gSOAP-1.3b": [
51183         "gSOAP Public License v1.3b",
51184         false,
51185         false
51186     ],
51187     "HaskellReport": [
51188         "Haskell Language Report License",
51189         false,
51190         false
51191     ],
51192     "Hippocratic-2.1": [
51193         "Hippocratic License 2.1",
51194         false,
51195         false
51196     ],
51197     "HPND": [
51198         "Historical Permission Notice and Disclaimer",
51199         true,
51200         false
51201     ],
51202     "HPND-sell-variant": [
51203         "Historical Permission Notice and Disclaimer - sell variant",
51204         false,
51205         false
51206     ],
51207     "HTMLTIDY": [
51208         "HTML Tidy License",
51209         false,
51210         false
51211     ],
51212     "IBM-pibs": [
51213         "IBM PowerPC Initialization and Boot Software",
51214         false,
51215         false
51216     ],
51217     "ICU": [
51218         "ICU License",
51219         false,
51220         false
51221     ],
51222     "IJG": [
51223         "Independent JPEG Group License",
51224         false,
51225         false
51226     ],
51227     "ImageMagick": [
51228         "ImageMagick License",
51229         false,
51230         false
51231     ],
51232     "iMatix": [
51233         "iMatix Standard Function Library Agreement",
51234         false,
51235         false
51236     ],
51237     "Imlib2": [
51238         "Imlib2 License",
51239         false,
51240         false
51241     ],
51242     "Info-ZIP": [
51243         "Info-ZIP License",
51244         false,
51245         false
51246     ],
51247     "Intel": [
51248         "Intel Open Source License",
51249         true,
51250         false
51251     ],
51252     "Intel-ACPI": [
51253         "Intel ACPI Software License Agreement",
51254         false,
51255         false
51256     ],
51257     "Interbase-1.0": [
51258         "Interbase Public License v1.0",
51259         false,
51260         false
51261     ],
51262     "IPA": [
51263         "IPA Font License",
51264         true,
51265         false
51266     ],
51267     "IPL-1.0": [
51268         "IBM Public License v1.0",
51269         true,
51270         false
51271     ],
51272     "ISC": [
51273         "ISC License",
51274         true,
51275         false
51276     ],
51277     "JasPer-2.0": [
51278         "JasPer License",
51279         false,
51280         false
51281     ],
51282     "JPNIC": [
51283         "Japan Network Information Center License",
51284         false,
51285         false
51286     ],
51287     "JSON": [
51288         "JSON License",
51289         false,
51290         false
51291     ],
51292     "LAL-1.2": [
51293         "Licence Art Libre 1.2",
51294         false,
51295         false
51296     ],
51297     "LAL-1.3": [
51298         "Licence Art Libre 1.3",
51299         false,
51300         false
51301     ],
51302     "Latex2e": [
51303         "Latex2e License",
51304         false,
51305         false
51306     ],
51307     "Leptonica": [
51308         "Leptonica License",
51309         false,
51310         false
51311     ],
51312     "LGPL-2.0": [
51313         "GNU Library General Public License v2 only",
51314         true,
51315         true
51316     ],
51317     "LGPL-2.0+": [
51318         "GNU Library General Public License v2 or later",
51319         true,
51320         true
51321     ],
51322     "LGPL-2.0-only": [
51323         "GNU Library General Public License v2 only",
51324         true,
51325         false
51326     ],
51327     "LGPL-2.0-or-later": [
51328         "GNU Library General Public License v2 or later",
51329         true,
51330         false
51331     ],
51332     "LGPL-2.1": [
51333         "GNU Lesser General Public License v2.1 only",
51334         true,
51335         true
51336     ],
51337     "LGPL-2.1+": [
51338         "GNU Library General Public License v2.1 or later",
51339         true,
51340         true
51341     ],
51342     "LGPL-2.1-only": [
51343         "GNU Lesser General Public License v2.1 only",
51344         true,
51345         false
51346     ],
51347     "LGPL-2.1-or-later": [
51348         "GNU Lesser General Public License v2.1 or later",
51349         true,
51350         false
51351     ],
51352     "LGPL-3.0": [
51353         "GNU Lesser General Public License v3.0 only",
51354         true,
51355         true
51356     ],
51357     "LGPL-3.0+": [
51358         "GNU Lesser General Public License v3.0 or later",
51359         true,
51360         true
51361     ],
51362     "LGPL-3.0-only": [
51363         "GNU Lesser General Public License v3.0 only",
51364         true,
51365         false
51366     ],
51367     "LGPL-3.0-or-later": [
51368         "GNU Lesser General Public License v3.0 or later",
51369         true,
51370         false
51371     ],
51372     "LGPLLR": [
51373         "Lesser General Public License For Linguistic Resources",
51374         false,
51375         false
51376     ],
51377     "Libpng": [
51378         "libpng License",
51379         false,
51380         false
51381     ],
51382     "libpng-2.0": [
51383         "PNG Reference Library version 2",
51384         false,
51385         false
51386     ],
51387     "libselinux-1.0": [
51388         "libselinux public domain notice",
51389         false,
51390         false
51391     ],
51392     "libtiff": [
51393         "libtiff License",
51394         false,
51395         false
51396     ],
51397     "LiLiQ-P-1.1": [
51398         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
51399         true,
51400         false
51401     ],
51402     "LiLiQ-R-1.1": [
51403         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
51404         true,
51405         false
51406     ],
51407     "LiLiQ-Rplus-1.1": [
51408         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
51409         true,
51410         false
51411     ],
51412     "Linux-man-pages-copyleft": [
51413         "Linux man-pages Copyleft",
51414         false,
51415         false
51416     ],
51417     "Linux-OpenIB": [
51418         "Linux Kernel Variant of OpenIB.org license",
51419         false,
51420         false
51421     ],
51422     "LPL-1.0": [
51423         "Lucent Public License Version 1.0",
51424         true,
51425         false
51426     ],
51427     "LPL-1.02": [
51428         "Lucent Public License v1.02",
51429         true,
51430         false
51431     ],
51432     "LPPL-1.0": [
51433         "LaTeX Project Public License v1.0",
51434         false,
51435         false
51436     ],
51437     "LPPL-1.1": [
51438         "LaTeX Project Public License v1.1",
51439         false,
51440         false
51441     ],
51442     "LPPL-1.2": [
51443         "LaTeX Project Public License v1.2",
51444         false,
51445         false
51446     ],
51447     "LPPL-1.3a": [
51448         "LaTeX Project Public License v1.3a",
51449         false,
51450         false
51451     ],
51452     "LPPL-1.3c": [
51453         "LaTeX Project Public License v1.3c",
51454         true,
51455         false
51456     ],
51457     "MakeIndex": [
51458         "MakeIndex License",
51459         false,
51460         false
51461     ],
51462     "MirOS": [
51463         "The MirOS Licence",
51464         true,
51465         false
51466     ],
51467     "MIT": [
51468         "MIT License",
51469         true,
51470         false
51471     ],
51472     "MIT-0": [
51473         "MIT No Attribution",
51474         true,
51475         false
51476     ],
51477     "MIT-advertising": [
51478         "Enlightenment License (e16)",
51479         false,
51480         false
51481     ],
51482     "MIT-CMU": [
51483         "CMU License",
51484         false,
51485         false
51486     ],
51487     "MIT-enna": [
51488         "enna License",
51489         false,
51490         false
51491     ],
51492     "MIT-feh": [
51493         "feh License",
51494         false,
51495         false
51496     ],
51497     "MIT-Modern-Variant": [
51498         "MIT License Modern Variant",
51499         true,
51500         false
51501     ],
51502     "MIT-open-group": [
51503         "MIT Open Group variant",
51504         false,
51505         false
51506     ],
51507     "MITNFA": [
51508         "MIT +no-false-attribs license",
51509         false,
51510         false
51511     ],
51512     "Motosoto": [
51513         "Motosoto License",
51514         true,
51515         false
51516     ],
51517     "mpich2": [
51518         "mpich2 License",
51519         false,
51520         false
51521     ],
51522     "MPL-1.0": [
51523         "Mozilla Public License 1.0",
51524         true,
51525         false
51526     ],
51527     "MPL-1.1": [
51528         "Mozilla Public License 1.1",
51529         true,
51530         false
51531     ],
51532     "MPL-2.0": [
51533         "Mozilla Public License 2.0",
51534         true,
51535         false
51536     ],
51537     "MPL-2.0-no-copyleft-exception": [
51538         "Mozilla Public License 2.0 (no copyleft exception)",
51539         true,
51540         false
51541     ],
51542     "MS-PL": [
51543         "Microsoft Public License",
51544         true,
51545         false
51546     ],
51547     "MS-RL": [
51548         "Microsoft Reciprocal License",
51549         true,
51550         false
51551     ],
51552     "MTLL": [
51553         "Matrix Template Library License",
51554         false,
51555         false
51556     ],
51557     "MulanPSL-1.0": [
51558         "Mulan Permissive Software License, Version 1",
51559         false,
51560         false
51561     ],
51562     "MulanPSL-2.0": [
51563         "Mulan Permissive Software License, Version 2",
51564         true,
51565         false
51566     ],
51567     "Multics": [
51568         "Multics License",
51569         true,
51570         false
51571     ],
51572     "Mup": [
51573         "Mup License",
51574         false,
51575         false
51576     ],
51577     "NAIST-2003": [
51578         "Nara Institute of Science and Technology License (2003)",
51579         false,
51580         false
51581     ],
51582     "NASA-1.3": [
51583         "NASA Open Source Agreement 1.3",
51584         true,
51585         false
51586     ],
51587     "Naumen": [
51588         "Naumen Public License",
51589         true,
51590         false
51591     ],
51592     "NBPL-1.0": [
51593         "Net Boolean Public License v1",
51594         false,
51595         false
51596     ],
51597     "NCGL-UK-2.0": [
51598         "Non-Commercial Government Licence",
51599         false,
51600         false
51601     ],
51602     "NCSA": [
51603         "University of Illinois/NCSA Open Source License",
51604         true,
51605         false
51606     ],
51607     "Net-SNMP": [
51608         "Net-SNMP License",
51609         false,
51610         false
51611     ],
51612     "NetCDF": [
51613         "NetCDF license",
51614         false,
51615         false
51616     ],
51617     "Newsletr": [
51618         "Newsletr License",
51619         false,
51620         false
51621     ],
51622     "NGPL": [
51623         "Nethack General Public License",
51624         true,
51625         false
51626     ],
51627     "NIST-PD": [
51628         "NIST Public Domain Notice",
51629         false,
51630         false
51631     ],
51632     "NIST-PD-fallback": [
51633         "NIST Public Domain Notice with license fallback",
51634         false,
51635         false
51636     ],
51637     "NLOD-1.0": [
51638         "Norwegian Licence for Open Government Data (NLOD) 1.0",
51639         false,
51640         false
51641     ],
51642     "NLOD-2.0": [
51643         "Norwegian Licence for Open Government Data (NLOD) 2.0",
51644         false,
51645         false
51646     ],
51647     "NLPL": [
51648         "No Limit Public License",
51649         false,
51650         false
51651     ],
51652     "Nokia": [
51653         "Nokia Open Source License",
51654         true,
51655         false
51656     ],
51657     "NOSL": [
51658         "Netizen Open Source License",
51659         false,
51660         false
51661     ],
51662     "Noweb": [
51663         "Noweb License",
51664         false,
51665         false
51666     ],
51667     "NPL-1.0": [
51668         "Netscape Public License v1.0",
51669         false,
51670         false
51671     ],
51672     "NPL-1.1": [
51673         "Netscape Public License v1.1",
51674         false,
51675         false
51676     ],
51677     "NPOSL-3.0": [
51678         "Non-Profit Open Software License 3.0",
51679         true,
51680         false
51681     ],
51682     "NRL": [
51683         "NRL License",
51684         false,
51685         false
51686     ],
51687     "NTP": [
51688         "NTP License",
51689         true,
51690         false
51691     ],
51692     "NTP-0": [
51693         "NTP No Attribution",
51694         false,
51695         false
51696     ],
51697     "Nunit": [
51698         "Nunit License",
51699         false,
51700         true
51701     ],
51702     "O-UDA-1.0": [
51703         "Open Use of Data Agreement v1.0",
51704         false,
51705         false
51706     ],
51707     "OCCT-PL": [
51708         "Open CASCADE Technology Public License",
51709         false,
51710         false
51711     ],
51712     "OCLC-2.0": [
51713         "OCLC Research Public License 2.0",
51714         true,
51715         false
51716     ],
51717     "ODbL-1.0": [
51718         "Open Data Commons Open Database License v1.0",
51719         false,
51720         false
51721     ],
51722     "ODC-By-1.0": [
51723         "Open Data Commons Attribution License v1.0",
51724         false,
51725         false
51726     ],
51727     "OFL-1.0": [
51728         "SIL Open Font License 1.0",
51729         false,
51730         false
51731     ],
51732     "OFL-1.0-no-RFN": [
51733         "SIL Open Font License 1.0 with no Reserved Font Name",
51734         false,
51735         false
51736     ],
51737     "OFL-1.0-RFN": [
51738         "SIL Open Font License 1.0 with Reserved Font Name",
51739         false,
51740         false
51741     ],
51742     "OFL-1.1": [
51743         "SIL Open Font License 1.1",
51744         true,
51745         false
51746     ],
51747     "OFL-1.1-no-RFN": [
51748         "SIL Open Font License 1.1 with no Reserved Font Name",
51749         true,
51750         false
51751     ],
51752     "OFL-1.1-RFN": [
51753         "SIL Open Font License 1.1 with Reserved Font Name",
51754         true,
51755         false
51756     ],
51757     "OGC-1.0": [
51758         "OGC Software License, Version 1.0",
51759         false,
51760         false
51761     ],
51762     "OGDL-Taiwan-1.0": [
51763         "Taiwan Open Government Data License, version 1.0",
51764         false,
51765         false
51766     ],
51767     "OGL-Canada-2.0": [
51768         "Open Government Licence - Canada",
51769         false,
51770         false
51771     ],
51772     "OGL-UK-1.0": [
51773         "Open Government Licence v1.0",
51774         false,
51775         false
51776     ],
51777     "OGL-UK-2.0": [
51778         "Open Government Licence v2.0",
51779         false,
51780         false
51781     ],
51782     "OGL-UK-3.0": [
51783         "Open Government Licence v3.0",
51784         false,
51785         false
51786     ],
51787     "OGTSL": [
51788         "Open Group Test Suite License",
51789         true,
51790         false
51791     ],
51792     "OLDAP-1.1": [
51793         "Open LDAP Public License v1.1",
51794         false,
51795         false
51796     ],
51797     "OLDAP-1.2": [
51798         "Open LDAP Public License v1.2",
51799         false,
51800         false
51801     ],
51802     "OLDAP-1.3": [
51803         "Open LDAP Public License v1.3",
51804         false,
51805         false
51806     ],
51807     "OLDAP-1.4": [
51808         "Open LDAP Public License v1.4",
51809         false,
51810         false
51811     ],
51812     "OLDAP-2.0": [
51813         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
51814         false,
51815         false
51816     ],
51817     "OLDAP-2.0.1": [
51818         "Open LDAP Public License v2.0.1",
51819         false,
51820         false
51821     ],
51822     "OLDAP-2.1": [
51823         "Open LDAP Public License v2.1",
51824         false,
51825         false
51826     ],
51827     "OLDAP-2.2": [
51828         "Open LDAP Public License v2.2",
51829         false,
51830         false
51831     ],
51832     "OLDAP-2.2.1": [
51833         "Open LDAP Public License v2.2.1",
51834         false,
51835         false
51836     ],
51837     "OLDAP-2.2.2": [
51838         "Open LDAP Public License 2.2.2",
51839         false,
51840         false
51841     ],
51842     "OLDAP-2.3": [
51843         "Open LDAP Public License v2.3",
51844         false,
51845         false
51846     ],
51847     "OLDAP-2.4": [
51848         "Open LDAP Public License v2.4",
51849         false,
51850         false
51851     ],
51852     "OLDAP-2.5": [
51853         "Open LDAP Public License v2.5",
51854         false,
51855         false
51856     ],
51857     "OLDAP-2.6": [
51858         "Open LDAP Public License v2.6",
51859         false,
51860         false
51861     ],
51862     "OLDAP-2.7": [
51863         "Open LDAP Public License v2.7",
51864         false,
51865         false
51866     ],
51867     "OLDAP-2.8": [
51868         "Open LDAP Public License v2.8",
51869         true,
51870         false
51871     ],
51872     "OML": [
51873         "Open Market License",
51874         false,
51875         false
51876     ],
51877     "OpenSSL": [
51878         "OpenSSL License",
51879         false,
51880         false
51881     ],
51882     "OPL-1.0": [
51883         "Open Public License v1.0",
51884         false,
51885         false
51886     ],
51887     "OPUBL-1.0": [
51888         "Open Publication License v1.0",
51889         false,
51890         false
51891     ],
51892     "OSET-PL-2.1": [
51893         "OSET Public License version 2.1",
51894         true,
51895         false
51896     ],
51897     "OSL-1.0": [
51898         "Open Software License 1.0",
51899         true,
51900         false
51901     ],
51902     "OSL-1.1": [
51903         "Open Software License 1.1",
51904         false,
51905         false
51906     ],
51907     "OSL-2.0": [
51908         "Open Software License 2.0",
51909         true,
51910         false
51911     ],
51912     "OSL-2.1": [
51913         "Open Software License 2.1",
51914         true,
51915         false
51916     ],
51917     "OSL-3.0": [
51918         "Open Software License 3.0",
51919         true,
51920         false
51921     ],
51922     "Parity-6.0.0": [
51923         "The Parity Public License 6.0.0",
51924         false,
51925         false
51926     ],
51927     "Parity-7.0.0": [
51928         "The Parity Public License 7.0.0",
51929         false,
51930         false
51931     ],
51932     "PDDL-1.0": [
51933         "Open Data Commons Public Domain Dedication & License 1.0",
51934         false,
51935         false
51936     ],
51937     "PHP-3.0": [
51938         "PHP License v3.0",
51939         true,
51940         false
51941     ],
51942     "PHP-3.01": [
51943         "PHP License v3.01",
51944         true,
51945         false
51946     ],
51947     "Plexus": [
51948         "Plexus Classworlds License",
51949         false,
51950         false
51951     ],
51952     "PolyForm-Noncommercial-1.0.0": [
51953         "PolyForm Noncommercial License 1.0.0",
51954         false,
51955         false
51956     ],
51957     "PolyForm-Small-Business-1.0.0": [
51958         "PolyForm Small Business License 1.0.0",
51959         false,
51960         false
51961     ],
51962     "PostgreSQL": [
51963         "PostgreSQL License",
51964         true,
51965         false
51966     ],
51967     "PSF-2.0": [
51968         "Python Software Foundation License 2.0",
51969         false,
51970         false
51971     ],
51972     "psfrag": [
51973         "psfrag License",
51974         false,
51975         false
51976     ],
51977     "psutils": [
51978         "psutils License",
51979         false,
51980         false
51981     ],
51982     "Python-2.0": [
51983         "Python License 2.0",
51984         true,
51985         false
51986     ],
51987     "Qhull": [
51988         "Qhull License",
51989         false,
51990         false
51991     ],
51992     "QPL-1.0": [
51993         "Q Public License 1.0",
51994         true,
51995         false
51996     ],
51997     "Rdisc": [
51998         "Rdisc License",
51999         false,
52000         false
52001     ],
52002     "RHeCos-1.1": [
52003         "Red Hat eCos Public License v1.1",
52004         false,
52005         false
52006     ],
52007     "RPL-1.1": [
52008         "Reciprocal Public License 1.1",
52009         true,
52010         false
52011     ],
52012     "RPL-1.5": [
52013         "Reciprocal Public License 1.5",
52014         true,
52015         false
52016     ],
52017     "RPSL-1.0": [
52018         "RealNetworks Public Source License v1.0",
52019         true,
52020         false
52021     ],
52022     "RSA-MD": [
52023         "RSA Message-Digest License",
52024         false,
52025         false
52026     ],
52027     "RSCPL": [
52028         "Ricoh Source Code Public License",
52029         true,
52030         false
52031     ],
52032     "Ruby": [
52033         "Ruby License",
52034         false,
52035         false
52036     ],
52037     "SAX-PD": [
52038         "Sax Public Domain Notice",
52039         false,
52040         false
52041     ],
52042     "Saxpath": [
52043         "Saxpath License",
52044         false,
52045         false
52046     ],
52047     "SCEA": [
52048         "SCEA Shared Source License",
52049         false,
52050         false
52051     ],
52052     "Sendmail": [
52053         "Sendmail License",
52054         false,
52055         false
52056     ],
52057     "Sendmail-8.23": [
52058         "Sendmail License 8.23",
52059         false,
52060         false
52061     ],
52062     "SGI-B-1.0": [
52063         "SGI Free Software License B v1.0",
52064         false,
52065         false
52066     ],
52067     "SGI-B-1.1": [
52068         "SGI Free Software License B v1.1",
52069         false,
52070         false
52071     ],
52072     "SGI-B-2.0": [
52073         "SGI Free Software License B v2.0",
52074         false,
52075         false
52076     ],
52077     "SHL-0.5": [
52078         "Solderpad Hardware License v0.5",
52079         false,
52080         false
52081     ],
52082     "SHL-0.51": [
52083         "Solderpad Hardware License, Version 0.51",
52084         false,
52085         false
52086     ],
52087     "SimPL-2.0": [
52088         "Simple Public License 2.0",
52089         true,
52090         false
52091     ],
52092     "SISSL": [
52093         "Sun Industry Standards Source License v1.1",
52094         true,
52095         false
52096     ],
52097     "SISSL-1.2": [
52098         "Sun Industry Standards Source License v1.2",
52099         false,
52100         false
52101     ],
52102     "Sleepycat": [
52103         "Sleepycat License",
52104         true,
52105         false
52106     ],
52107     "SMLNJ": [
52108         "Standard ML of New Jersey License",
52109         false,
52110         false
52111     ],
52112     "SMPPL": [
52113         "Secure Messaging Protocol Public License",
52114         false,
52115         false
52116     ],
52117     "SNIA": [
52118         "SNIA Public License 1.1",
52119         false,
52120         false
52121     ],
52122     "Spencer-86": [
52123         "Spencer License 86",
52124         false,
52125         false
52126     ],
52127     "Spencer-94": [
52128         "Spencer License 94",
52129         false,
52130         false
52131     ],
52132     "Spencer-99": [
52133         "Spencer License 99",
52134         false,
52135         false
52136     ],
52137     "SPL-1.0": [
52138         "Sun Public License v1.0",
52139         true,
52140         false
52141     ],
52142     "SSH-OpenSSH": [
52143         "SSH OpenSSH license",
52144         false,
52145         false
52146     ],
52147     "SSH-short": [
52148         "SSH short notice",
52149         false,
52150         false
52151     ],
52152     "SSPL-1.0": [
52153         "Server Side Public License, v 1",
52154         false,
52155         false
52156     ],
52157     "StandardML-NJ": [
52158         "Standard ML of New Jersey License",
52159         false,
52160         true
52161     ],
52162     "SugarCRM-1.1.3": [
52163         "SugarCRM Public License v1.1.3",
52164         false,
52165         false
52166     ],
52167     "SWL": [
52168         "Scheme Widget Library (SWL) Software License Agreement",
52169         false,
52170         false
52171     ],
52172     "TAPR-OHL-1.0": [
52173         "TAPR Open Hardware License v1.0",
52174         false,
52175         false
52176     ],
52177     "TCL": [
52178         "TCL/TK License",
52179         false,
52180         false
52181     ],
52182     "TCP-wrappers": [
52183         "TCP Wrappers License",
52184         false,
52185         false
52186     ],
52187     "TMate": [
52188         "TMate Open Source License",
52189         false,
52190         false
52191     ],
52192     "TORQUE-1.1": [
52193         "TORQUE v2.5+ Software License v1.1",
52194         false,
52195         false
52196     ],
52197     "TOSL": [
52198         "Trusster Open Source License",
52199         false,
52200         false
52201     ],
52202     "TU-Berlin-1.0": [
52203         "Technische Universitaet Berlin License 1.0",
52204         false,
52205         false
52206     ],
52207     "TU-Berlin-2.0": [
52208         "Technische Universitaet Berlin License 2.0",
52209         false,
52210         false
52211     ],
52212     "UCL-1.0": [
52213         "Upstream Compatibility License v1.0",
52214         true,
52215         false
52216     ],
52217     "Unicode-DFS-2015": [
52218         "Unicode License Agreement - Data Files and Software (2015)",
52219         false,
52220         false
52221     ],
52222     "Unicode-DFS-2016": [
52223         "Unicode License Agreement - Data Files and Software (2016)",
52224         true,
52225         false
52226     ],
52227     "Unicode-TOU": [
52228         "Unicode Terms of Use",
52229         false,
52230         false
52231     ],
52232     "Unlicense": [
52233         "The Unlicense",
52234         true,
52235         false
52236     ],
52237     "UPL-1.0": [
52238         "Universal Permissive License v1.0",
52239         true,
52240         false
52241     ],
52242     "Vim": [
52243         "Vim License",
52244         false,
52245         false
52246     ],
52247     "VOSTROM": [
52248         "VOSTROM Public License for Open Source",
52249         false,
52250         false
52251     ],
52252     "VSL-1.0": [
52253         "Vovida Software License v1.0",
52254         true,
52255         false
52256     ],
52257     "W3C": [
52258         "W3C Software Notice and License (2002-12-31)",
52259         true,
52260         false
52261     ],
52262     "W3C-19980720": [
52263         "W3C Software Notice and License (1998-07-20)",
52264         false,
52265         false
52266     ],
52267     "W3C-20150513": [
52268         "W3C Software Notice and Document License (2015-05-13)",
52269         false,
52270         false
52271     ],
52272     "Watcom-1.0": [
52273         "Sybase Open Watcom Public License 1.0",
52274         true,
52275         false
52276     ],
52277     "Wsuipa": [
52278         "Wsuipa License",
52279         false,
52280         false
52281     ],
52282     "WTFPL": [
52283         "Do What The F*ck You Want To Public License",
52284         false,
52285         false
52286     ],
52287     "wxWindows": [
52288         "wxWindows Library License",
52289         true,
52290         true
52291     ],
52292     "X11": [
52293         "X11 License",
52294         false,
52295         false
52296     ],
52297     "Xerox": [
52298         "Xerox License",
52299         false,
52300         false
52301     ],
52302     "XFree86-1.1": [
52303         "XFree86 License 1.1",
52304         false,
52305         false
52306     ],
52307     "xinetd": [
52308         "xinetd License",
52309         false,
52310         false
52311     ],
52312     "Xnet": [
52313         "X.Net License",
52314         true,
52315         false
52316     ],
52317     "xpp": [
52318         "XPP License",
52319         false,
52320         false
52321     ],
52322     "XSkat": [
52323         "XSkat License",
52324         false,
52325         false
52326     ],
52327     "YPL-1.0": [
52328         "Yahoo! Public License v1.0",
52329         false,
52330         false
52331     ],
52332     "YPL-1.1": [
52333         "Yahoo! Public License v1.1",
52334         false,
52335         false
52336     ],
52337     "Zed": [
52338         "Zed License",
52339         false,
52340         false
52341     ],
52342     "Zend-2.0": [
52343         "Zend License v2.0",
52344         false,
52345         false
52346     ],
52347     "Zimbra-1.3": [
52348         "Zimbra Public License v1.3",
52349         false,
52350         false
52351     ],
52352     "Zimbra-1.4": [
52353         "Zimbra Public License v1.4",
52354         false,
52355         false
52356     ],
52357     "Zlib": [
52358         "zlib License",
52359         true,
52360         false
52361     ],
52362     "zlib-acknowledgement": [
52363         "zlib/libpng License with Acknowledgement",
52364         false,
52365         false
52366     ],
52367     "ZPL-1.1": [
52368         "Zope Public License 1.1",
52369         false,
52370         false
52371     ],
52372     "ZPL-2.0": [
52373         "Zope Public License 2.0",
52374         true,
52375         false
52376     ],
52377     "ZPL-2.1": [
52378         "Zope Public License 2.1",
52379         true,
52380         false
52381     ]
52382 }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
52383 $\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
52384 \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
52385 \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
52386 \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
52387 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
52388 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
52389 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
52390   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
52391     <security>\r
52392       <requestedPrivileges>\r
52393         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
52394       </requestedPrivileges>\r
52395     </security>\r
52396   </trustInfo>\r
52397   <dependency>\r
52398     <dependentAssembly>\r
52399       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
52400     </dependentAssembly>\r
52401   </dependency>\r
52402 </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
52403
52404 /*
52405  * This file is part of the Symfony package.
52406  *
52407  * (c) Fabien Potencier <fabien@symfony.com>
52408  *
52409  * For the full copyright and license information, please view the LICENSE
52410  * file that was distributed with this source code.
52411  */
52412
52413 use Symfony\Polyfill\Mbstring as p;
52414
52415 if (!function_exists('mb_convert_variables')) {
52416     /**
52417      * Convert character code in variable(s)
52418      */
52419     function mb_convert_variables($to_encoding, $from_encoding, &$var, &...$vars)
52420     {
52421         $vars = [&$var, ...$vars];
52422
52423         $ok = true;
52424         array_walk_recursive($vars, function (&$v) use (&$ok, $to_encoding, $from_encoding) {
52425             if (false === $v = p\Mbstring::mb_convert_encoding($v, $to_encoding, $from_encoding)) {
52426                 $ok = false;
52427             }
52428         });
52429
52430         return $ok ? $from_encoding : false;
52431     }
52432 }
52433 <?php
52434
52435
52436
52437
52438
52439
52440
52441
52442
52443
52444 namespace Symfony\Component\Console;
52445
52446 use Symfony\Component\Console\Command\Command;
52447 use Symfony\Component\Console\Command\HelpCommand;
52448 use Symfony\Component\Console\Command\ListCommand;
52449 use Symfony\Component\Console\Descriptor\TextDescriptor;
52450 use Symfony\Component\Console\Descriptor\XmlDescriptor;
52451 use Symfony\Component\Console\Event\ConsoleCommandEvent;
52452 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
52453 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
52454 use Symfony\Component\Console\Exception\CommandNotFoundException;
52455 use Symfony\Component\Console\Exception\ExceptionInterface;
52456 use Symfony\Component\Console\Exception\LogicException;
52457 use Symfony\Component\Console\Formatter\OutputFormatter;
52458 use Symfony\Component\Console\Helper\DebugFormatterHelper;
52459 use Symfony\Component\Console\Helper\DialogHelper;
52460 use Symfony\Component\Console\Helper\FormatterHelper;
52461 use Symfony\Component\Console\Helper\Helper;
52462 use Symfony\Component\Console\Helper\HelperSet;
52463 use Symfony\Component\Console\Helper\ProcessHelper;
52464 use Symfony\Component\Console\Helper\ProgressHelper;
52465 use Symfony\Component\Console\Helper\QuestionHelper;
52466 use Symfony\Component\Console\Helper\TableHelper;
52467 use Symfony\Component\Console\Input\ArgvInput;
52468 use Symfony\Component\Console\Input\ArrayInput;
52469 use Symfony\Component\Console\Input\InputArgument;
52470 use Symfony\Component\Console\Input\InputAwareInterface;
52471 use Symfony\Component\Console\Input\InputDefinition;
52472 use Symfony\Component\Console\Input\InputInterface;
52473 use Symfony\Component\Console\Input\InputOption;
52474 use Symfony\Component\Console\Output\BufferedOutput;
52475 use Symfony\Component\Console\Output\ConsoleOutput;
52476 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52477 use Symfony\Component\Console\Output\OutputInterface;
52478 use Symfony\Component\Debug\Exception\FatalThrowableError;
52479 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
52480
52481
52482
52483
52484
52485
52486
52487
52488
52489
52490
52491
52492
52493
52494
52495
52496 class Application
52497 {
52498 private $commands = array();
52499 private $wantHelps = false;
52500 private $runningCommand;
52501 private $name;
52502 private $version;
52503 private $catchExceptions = true;
52504 private $autoExit = true;
52505 private $definition;
52506 private $helperSet;
52507 private $dispatcher;
52508 private $terminalDimensions;
52509 private $defaultCommand;
52510 private $initialized;
52511
52512
52513
52514
52515
52516 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
52517 {
52518 $this->name = $name;
52519 $this->version = $version;
52520 $this->defaultCommand = 'list';
52521 }
52522
52523 public function setDispatcher(EventDispatcherInterface $dispatcher)
52524 {
52525 $this->dispatcher = $dispatcher;
52526 }
52527
52528
52529
52530
52531
52532
52533
52534
52535 public function run(InputInterface $input = null, OutputInterface $output = null)
52536 {
52537 if (null === $input) {
52538 $input = new ArgvInput();
52539 }
52540
52541 if (null === $output) {
52542 $output = new ConsoleOutput();
52543 }
52544
52545 $this->configureIO($input, $output);
52546
52547 try {
52548 $e = null;
52549 $exitCode = $this->doRun($input, $output);
52550 } catch (\Exception $e) {
52551 }
52552
52553 if (null !== $e) {
52554 if (!$this->catchExceptions) {
52555 throw $e;
52556 }
52557
52558 if ($output instanceof ConsoleOutputInterface) {
52559 $this->renderException($e, $output->getErrorOutput());
52560 } else {
52561 $this->renderException($e, $output);
52562 }
52563
52564 $exitCode = $this->getExitCodeForThrowable($e);
52565 }
52566
52567 if ($this->autoExit) {
52568 if ($exitCode > 255) {
52569 $exitCode = 255;
52570 }
52571
52572 exit($exitCode);
52573 }
52574
52575 return $exitCode;
52576 }
52577
52578
52579
52580
52581
52582
52583 public function doRun(InputInterface $input, OutputInterface $output)
52584 {
52585 if (true === $input->hasParameterOption(array('--version', '-V'))) {
52586 $output->writeln($this->getLongVersion());
52587
52588 return 0;
52589 }
52590
52591 $name = $this->getCommandName($input);
52592 if (true === $input->hasParameterOption(array('--help', '-h'))) {
52593 if (!$name) {
52594 $name = 'help';
52595 $input = new ArrayInput(array('command' => 'help'));
52596 } else {
52597 $this->wantHelps = true;
52598 }
52599 }
52600
52601 if (!$name) {
52602 $name = $this->defaultCommand;
52603 $definition = $this->getDefinition();
52604 $definition->setArguments(array_merge(
52605 $definition->getArguments(),
52606 array(
52607 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
52608 )
52609 ));
52610 }
52611
52612 $this->runningCommand = null;
52613
52614 $command = $this->find($name);
52615
52616 $this->runningCommand = $command;
52617 $exitCode = $this->doRunCommand($command, $input, $output);
52618 $this->runningCommand = null;
52619
52620 return $exitCode;
52621 }
52622
52623 public function setHelperSet(HelperSet $helperSet)
52624 {
52625 $this->helperSet = $helperSet;
52626 }
52627
52628
52629
52630
52631
52632
52633 public function getHelperSet()
52634 {
52635 if (!$this->helperSet) {
52636 $this->helperSet = $this->getDefaultHelperSet();
52637 }
52638
52639 return $this->helperSet;
52640 }
52641
52642 public function setDefinition(InputDefinition $definition)
52643 {
52644 $this->definition = $definition;
52645 }
52646
52647
52648
52649
52650
52651
52652 public function getDefinition()
52653 {
52654 if (!$this->definition) {
52655 $this->definition = $this->getDefaultInputDefinition();
52656 }
52657
52658 return $this->definition;
52659 }
52660
52661
52662
52663
52664
52665
52666 public function getHelp()
52667 {
52668 return $this->getLongVersion();
52669 }
52670
52671
52672
52673
52674
52675
52676 public function setCatchExceptions($boolean)
52677 {
52678 $this->catchExceptions = (bool) $boolean;
52679 }
52680
52681
52682
52683
52684
52685
52686 public function setAutoExit($boolean)
52687 {
52688 $this->autoExit = (bool) $boolean;
52689 }
52690
52691
52692
52693
52694
52695
52696 public function getName()
52697 {
52698 return $this->name;
52699 }
52700
52701
52702
52703
52704
52705
52706 public function setName($name)
52707 {
52708 $this->name = $name;
52709 }
52710
52711
52712
52713
52714
52715
52716 public function getVersion()
52717 {
52718 return $this->version;
52719 }
52720
52721
52722
52723
52724
52725
52726 public function setVersion($version)
52727 {
52728 $this->version = $version;
52729 }
52730
52731
52732
52733
52734
52735
52736 public function getLongVersion()
52737 {
52738 if ('UNKNOWN' !== $this->getName()) {
52739 if ('UNKNOWN' !== $this->getVersion()) {
52740 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
52741 }
52742
52743 return sprintf('<info>%s</info>', $this->getName());
52744 }
52745
52746 return '<info>Console Tool</info>';
52747 }
52748
52749
52750
52751
52752
52753
52754
52755
52756 public function register($name)
52757 {
52758 return $this->add(new Command($name));
52759 }
52760
52761
52762
52763
52764
52765
52766
52767
52768 public function addCommands(array $commands)
52769 {
52770 foreach ($commands as $command) {
52771 $this->add($command);
52772 }
52773 }
52774
52775
52776
52777
52778
52779
52780
52781
52782
52783 public function add(Command $command)
52784 {
52785 $this->init();
52786
52787 $command->setApplication($this);
52788
52789 if (!$command->isEnabled()) {
52790 $command->setApplication(null);
52791
52792 return;
52793 }
52794
52795 if (null === $command->getDefinition()) {
52796 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($command)));
52797 }
52798
52799 $this->commands[$command->getName()] = $command;
52800
52801 foreach ($command->getAliases() as $alias) {
52802 $this->commands[$alias] = $command;
52803 }
52804
52805 return $command;
52806 }
52807
52808
52809
52810
52811
52812
52813
52814
52815
52816
52817 public function get($name)
52818 {
52819 $this->init();
52820
52821 if (!isset($this->commands[$name])) {
52822 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
52823 }
52824
52825 $command = $this->commands[$name];
52826
52827 if ($this->wantHelps) {
52828 $this->wantHelps = false;
52829
52830 $helpCommand = $this->get('help');
52831 $helpCommand->setCommand($command);
52832
52833 return $helpCommand;
52834 }
52835
52836 return $command;
52837 }
52838
52839
52840
52841
52842
52843
52844
52845
52846 public function has($name)
52847 {
52848 $this->init();
52849
52850 return isset($this->commands[$name]);
52851 }
52852
52853
52854
52855
52856
52857
52858
52859
52860 public function getNamespaces()
52861 {
52862 $namespaces = array();
52863 foreach ($this->all() as $command) {
52864 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
52865
52866 foreach ($command->getAliases() as $alias) {
52867 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
52868 }
52869 }
52870
52871 return array_values(array_unique(array_filter($namespaces)));
52872 }
52873
52874
52875
52876
52877
52878
52879
52880
52881
52882
52883 public function findNamespace($namespace)
52884 {
52885 $allNamespaces = $this->getNamespaces();
52886 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
52887 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
52888
52889 if (empty($namespaces)) {
52890 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
52891
52892 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
52893 if (1 == \count($alternatives)) {
52894 $message .= "\n\nDid you mean this?\n    ";
52895 } else {
52896 $message .= "\n\nDid you mean one of these?\n    ";
52897 }
52898
52899 $message .= implode("\n    ", $alternatives);
52900 }
52901
52902 throw new CommandNotFoundException($message, $alternatives);
52903 }
52904
52905 $exact = \in_array($namespace, $namespaces, true);
52906 if (\count($namespaces) > 1 && !$exact) {
52907 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
52908 }
52909
52910 return $exact ? $namespace : reset($namespaces);
52911 }
52912
52913
52914
52915
52916
52917
52918
52919
52920
52921
52922
52923
52924
52925 public function find($name)
52926 {
52927 $this->init();
52928 $aliases = array();
52929 $allCommands = array_keys($this->commands);
52930 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
52931 $commands = preg_grep('{^'.$expr.'}', $allCommands);
52932
52933 if (empty($commands) || \count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
52934 if (false !== $pos = strrpos($name, ':')) {
52935
52936 $this->findNamespace(substr($name, 0, $pos));
52937 }
52938
52939 $message = sprintf('Command "%s" is not defined.', $name);
52940
52941 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
52942 if (1 == \count($alternatives)) {
52943 $message .= "\n\nDid you mean this?\n    ";
52944 } else {
52945 $message .= "\n\nDid you mean one of these?\n    ";
52946 }
52947 $message .= implode("\n    ", $alternatives);
52948 }
52949
52950 throw new CommandNotFoundException($message, $alternatives);
52951 }
52952
52953
52954 if (\count($commands) > 1) {
52955 $commandList = $this->commands;
52956 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
52957 $commandName = $commandList[$nameOrAlias]->getName();
52958 $aliases[$nameOrAlias] = $commandName;
52959
52960 return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
52961 });
52962 }
52963
52964 $exact = \in_array($name, $commands, true) || isset($aliases[$name]);
52965 if (!$exact && \count($commands) > 1) {
52966 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
52967
52968 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
52969 }
52970
52971 return $this->get($exact ? $name : reset($commands));
52972 }
52973
52974
52975
52976
52977
52978
52979
52980
52981
52982
52983 public function all($namespace = null)
52984 {
52985 $this->init();
52986
52987 if (null === $namespace) {
52988 return $this->commands;
52989 }
52990
52991 $commands = array();
52992 foreach ($this->commands as $name => $command) {
52993 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
52994 $commands[$name] = $command;
52995 }
52996 }
52997
52998 return $commands;
52999 }
53000
53001
53002
53003
53004
53005
53006
53007
53008 public static function getAbbreviations($names)
53009 {
53010 $abbrevs = array();
53011 foreach ($names as $name) {
53012 for ($len = \strlen($name); $len > 0; --$len) {
53013 $abbrev = substr($name, 0, $len);
53014 $abbrevs[$abbrev][] = $name;
53015 }
53016 }
53017
53018 return $abbrevs;
53019 }
53020
53021
53022
53023
53024
53025
53026
53027
53028
53029
53030
53031 public function asText($namespace = null, $raw = false)
53032 {
53033 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
53034
53035 $descriptor = new TextDescriptor();
53036 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
53037 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
53038
53039 return $output->fetch();
53040 }
53041
53042
53043
53044
53045
53046
53047
53048
53049
53050
53051
53052 public function asXml($namespace = null, $asDom = false)
53053 {
53054 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
53055
53056 $descriptor = new XmlDescriptor();
53057
53058 if ($asDom) {
53059 return $descriptor->getApplicationDocument($this, $namespace);
53060 }
53061
53062 $output = new BufferedOutput();
53063 $descriptor->describe($output, $this, array('namespace' => $namespace));
53064
53065 return $output->fetch();
53066 }
53067
53068
53069
53070
53071 public function renderException($e, $output)
53072 {
53073 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
53074
53075 do {
53076 $title = sprintf('  [%s]  ', \get_class($e));
53077
53078 $len = Helper::strlen($title);
53079
53080 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
53081
53082 if (\defined('HHVM_VERSION') && $width > 1 << 31) {
53083 $width = 1 << 31;
53084 }
53085 $lines = array();
53086 foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) {
53087 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
53088
53089 $lineLength = Helper::strlen($line) + 4;
53090 $lines[] = array($line, $lineLength);
53091
53092 $len = max($lineLength, $len);
53093 }
53094 }
53095
53096 $messages = array();
53097 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
53098 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
53099 foreach ($lines as $line) {
53100 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
53101 }
53102 $messages[] = $emptyLine;
53103 $messages[] = '';
53104
53105 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
53106
53107 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
53108 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
53109
53110
53111 $trace = $e->getTrace();
53112 array_unshift($trace, array(
53113 'function' => '',
53114 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a',
53115 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a',
53116 'args' => array(),
53117 ));
53118
53119 for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
53120 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
53121 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
53122 $function = $trace[$i]['function'];
53123 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
53124 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
53125
53126 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
53127 }
53128
53129 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
53130 }
53131 } while ($e = $e->getPrevious());
53132
53133 if (null !== $this->runningCommand) {
53134 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
53135 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
53136 }
53137 }
53138
53139
53140
53141
53142
53143
53144 protected function getTerminalWidth()
53145 {
53146 $dimensions = $this->getTerminalDimensions();
53147
53148 return $dimensions[0];
53149 }
53150
53151
53152
53153
53154
53155
53156 protected function getTerminalHeight()
53157 {
53158 $dimensions = $this->getTerminalDimensions();
53159
53160 return $dimensions[1];
53161 }
53162
53163
53164
53165
53166
53167
53168 public function getTerminalDimensions()
53169 {
53170 if ($this->terminalDimensions) {
53171 return $this->terminalDimensions;
53172 }
53173
53174 if ('\\' === \DIRECTORY_SEPARATOR) {
53175
53176 if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
53177 return array((int) $matches[1], (int) $matches[2]);
53178 }
53179
53180 if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
53181 return array((int) $matches[1], (int) $matches[2]);
53182 }
53183 }
53184
53185 if ($sttyString = $this->getSttyColumns()) {
53186
53187 if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
53188 return array((int) $matches[2], (int) $matches[1]);
53189 }
53190
53191 if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
53192 return array((int) $matches[2], (int) $matches[1]);
53193 }
53194 }
53195
53196 return array(null, null);
53197 }
53198
53199
53200
53201
53202
53203
53204
53205
53206
53207
53208
53209 public function setTerminalDimensions($width, $height)
53210 {
53211 $this->terminalDimensions = array($width, $height);
53212
53213 return $this;
53214 }
53215
53216
53217
53218
53219 protected function configureIO(InputInterface $input, OutputInterface $output)
53220 {
53221 if (true === $input->hasParameterOption(array('--ansi'))) {
53222 $output->setDecorated(true);
53223 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
53224 $output->setDecorated(false);
53225 }
53226
53227 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
53228 $input->setInteractive(false);
53229 } elseif (\function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
53230 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
53231 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
53232 $input->setInteractive(false);
53233 }
53234 }
53235
53236 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
53237 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
53238 $input->setInteractive(false);
53239 } else {
53240 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) {
53241 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
53242 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) {
53243 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
53244 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
53245 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
53246 }
53247 }
53248 }
53249
53250
53251
53252
53253
53254
53255
53256
53257
53258 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
53259 {
53260 foreach ($command->getHelperSet() as $helper) {
53261 if ($helper instanceof InputAwareInterface) {
53262 $helper->setInput($input);
53263 }
53264 }
53265
53266 if (null === $this->dispatcher) {
53267 return $command->run($input, $output);
53268 }
53269
53270
53271 try {
53272 $command->mergeApplicationDefinition();
53273 $input->bind($command->getDefinition());
53274 } catch (ExceptionInterface $e) {
53275
53276 }
53277
53278 $event = new ConsoleCommandEvent($command, $input, $output);
53279 $e = null;
53280
53281 try {
53282 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
53283
53284 if ($event->commandShouldRun()) {
53285 $exitCode = $command->run($input, $output);
53286 } else {
53287 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
53288 }
53289 } catch (\Exception $e) {
53290 } catch (\Throwable $e) {
53291 }
53292 if (null !== $e) {
53293 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
53294 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
53295 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
53296
53297 if ($x !== $event->getException()) {
53298 $e = $event->getException();
53299 }
53300
53301 $exitCode = $this->getExitCodeForThrowable($e);
53302 }
53303
53304 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
53305 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
53306
53307 if (null !== $e) {
53308 throw $e;
53309 }
53310
53311 return $event->getExitCode();
53312 }
53313
53314
53315
53316
53317
53318
53319 protected function getCommandName(InputInterface $input)
53320 {
53321 return $input->getFirstArgument();
53322 }
53323
53324
53325
53326
53327
53328
53329 protected function getDefaultInputDefinition()
53330 {
53331 return new InputDefinition(array(
53332 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
53333
53334 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
53335 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
53336 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'),
53337 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
53338 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
53339 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
53340 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
53341 ));
53342 }
53343
53344
53345
53346
53347
53348
53349 protected function getDefaultCommands()
53350 {
53351 return array(new HelpCommand(), new ListCommand());
53352 }
53353
53354
53355
53356
53357
53358
53359 protected function getDefaultHelperSet()
53360 {
53361 return new HelperSet(array(
53362 new FormatterHelper(),
53363 new DialogHelper(false),
53364 new ProgressHelper(false),
53365 new TableHelper(false),
53366 new DebugFormatterHelper(),
53367 new ProcessHelper(),
53368 new QuestionHelper(),
53369 ));
53370 }
53371
53372
53373
53374
53375
53376
53377 private function getSttyColumns()
53378 {
53379 if (!\function_exists('proc_open')) {
53380 return;
53381 }
53382
53383 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
53384 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
53385 if (\is_resource($process)) {
53386 $info = stream_get_contents($pipes[1]);
53387 fclose($pipes[1]);
53388 fclose($pipes[2]);
53389 proc_close($process);
53390
53391 return $info;
53392 }
53393 }
53394
53395
53396
53397
53398
53399
53400 private function getConsoleMode()
53401 {
53402 if (!\function_exists('proc_open')) {
53403 return;
53404 }
53405
53406 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
53407 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
53408 if (\is_resource($process)) {
53409 $info = stream_get_contents($pipes[1]);
53410 fclose($pipes[1]);
53411 fclose($pipes[2]);
53412 proc_close($process);
53413
53414 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
53415 return $matches[2].'x'.$matches[1];
53416 }
53417 }
53418 }
53419
53420
53421
53422
53423
53424
53425
53426
53427 private function getAbbreviationSuggestions($abbrevs)
53428 {
53429 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], \count($abbrevs) > 2 ? sprintf(' and %d more', \count($abbrevs) - 2) : '');
53430 }
53431
53432
53433
53434
53435
53436
53437
53438
53439
53440
53441
53442 public function extractNamespace($name, $limit = null)
53443 {
53444 $parts = explode(':', $name);
53445 array_pop($parts);
53446
53447 return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
53448 }
53449
53450
53451
53452
53453
53454
53455
53456
53457
53458
53459 private function findAlternatives($name, $collection)
53460 {
53461 $threshold = 1e3;
53462 $alternatives = array();
53463
53464 $collectionParts = array();
53465 foreach ($collection as $item) {
53466 $collectionParts[$item] = explode(':', $item);
53467 }
53468
53469 foreach (explode(':', $name) as $i => $subname) {
53470 foreach ($collectionParts as $collectionName => $parts) {
53471 $exists = isset($alternatives[$collectionName]);
53472 if (!isset($parts[$i]) && $exists) {
53473 $alternatives[$collectionName] += $threshold;
53474 continue;
53475 } elseif (!isset($parts[$i])) {
53476 continue;
53477 }
53478
53479 $lev = levenshtein($subname, $parts[$i]);
53480 if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
53481 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
53482 } elseif ($exists) {
53483 $alternatives[$collectionName] += $threshold;
53484 }
53485 }
53486 }
53487
53488 foreach ($collection as $item) {
53489 $lev = levenshtein($name, $item);
53490 if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) {
53491 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
53492 }
53493 }
53494
53495 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
53496 asort($alternatives);
53497
53498 return array_keys($alternatives);
53499 }
53500
53501
53502
53503
53504
53505
53506 public function setDefaultCommand($commandName)
53507 {
53508 $this->defaultCommand = $commandName;
53509 }
53510
53511 private function splitStringByWidth($string, $width)
53512 {
53513
53514
53515
53516 if (false === $encoding = mb_detect_encoding($string, null, true)) {
53517 return str_split($string, $width);
53518 }
53519
53520 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
53521 $lines = array();
53522 $line = '';
53523 foreach (preg_split('//u', $utf8String) as $char) {
53524
53525 if (mb_strwidth($line.$char, 'utf8') <= $width) {
53526 $line .= $char;
53527 continue;
53528 }
53529
53530 $lines[] = str_pad($line, $width);
53531 $line = $char;
53532 }
53533
53534 $lines[] = \count($lines) ? str_pad($line, $width) : $line;
53535
53536 mb_convert_variables($encoding, 'utf8', $lines);
53537
53538 return $lines;
53539 }
53540
53541
53542
53543
53544
53545
53546
53547
53548 private function extractAllNamespaces($name)
53549 {
53550
53551 $parts = explode(':', $name, -1);
53552 $namespaces = array();
53553
53554 foreach ($parts as $part) {
53555 if (\count($namespaces)) {
53556 $namespaces[] = end($namespaces).':'.$part;
53557 } else {
53558 $namespaces[] = $part;
53559 }
53560 }
53561
53562 return $namespaces;
53563 }
53564
53565 private function init()
53566 {
53567 if ($this->initialized) {
53568 return;
53569 }
53570 $this->initialized = true;
53571
53572 foreach ($this->getDefaultCommands() as $command) {
53573 $this->add($command);
53574 }
53575 }
53576
53577
53578
53579
53580
53581
53582 private function getExitCodeForThrowable($throwable)
53583 {
53584 $exitCode = $throwable->getCode();
53585 if (is_numeric($exitCode)) {
53586 $exitCode = (int) $exitCode;
53587 if (0 === $exitCode) {
53588 $exitCode = 1;
53589 }
53590 } else {
53591 $exitCode = 1;
53592 }
53593
53594 return $exitCode;
53595 }
53596 }
53597 <?php
53598
53599
53600
53601
53602
53603
53604
53605
53606
53607
53608 namespace Symfony\Component\Console\Command;
53609
53610 use Symfony\Component\Console\Application;
53611 use Symfony\Component\Console\Descriptor\TextDescriptor;
53612 use Symfony\Component\Console\Descriptor\XmlDescriptor;
53613 use Symfony\Component\Console\Exception\ExceptionInterface;
53614 use Symfony\Component\Console\Exception\InvalidArgumentException;
53615 use Symfony\Component\Console\Exception\LogicException;
53616 use Symfony\Component\Console\Helper\HelperSet;
53617 use Symfony\Component\Console\Input\InputArgument;
53618 use Symfony\Component\Console\Input\InputDefinition;
53619 use Symfony\Component\Console\Input\InputInterface;
53620 use Symfony\Component\Console\Input\InputOption;
53621 use Symfony\Component\Console\Output\BufferedOutput;
53622 use Symfony\Component\Console\Output\OutputInterface;
53623
53624
53625
53626
53627
53628
53629 class Command
53630 {
53631 private $application;
53632 private $name;
53633 private $processTitle;
53634 private $aliases = array();
53635 private $definition;
53636 private $help;
53637 private $description;
53638 private $ignoreValidationErrors = false;
53639 private $applicationDefinitionMerged = false;
53640 private $applicationDefinitionMergedWithArgs = false;
53641 private $code;
53642 private $synopsis = array();
53643 private $usages = array();
53644 private $helperSet;
53645
53646
53647
53648
53649
53650
53651 public function __construct($name = null)
53652 {
53653 $this->definition = new InputDefinition();
53654
53655 if (null !== $name) {
53656 $this->setName($name);
53657 }
53658
53659 $this->configure();
53660
53661 if (!$this->name) {
53662 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($this)));
53663 }
53664 }
53665
53666
53667
53668
53669
53670
53671 public function ignoreValidationErrors()
53672 {
53673 $this->ignoreValidationErrors = true;
53674 }
53675
53676 public function setApplication(Application $application = null)
53677 {
53678 $this->application = $application;
53679 if ($application) {
53680 $this->setHelperSet($application->getHelperSet());
53681 } else {
53682 $this->helperSet = null;
53683 }
53684 }
53685
53686 public function setHelperSet(HelperSet $helperSet)
53687 {
53688 $this->helperSet = $helperSet;
53689 }
53690
53691
53692
53693
53694
53695
53696 public function getHelperSet()
53697 {
53698 return $this->helperSet;
53699 }
53700
53701
53702
53703
53704
53705
53706 public function getApplication()
53707 {
53708 return $this->application;
53709 }
53710
53711
53712
53713
53714
53715
53716
53717
53718
53719 public function isEnabled()
53720 {
53721 return true;
53722 }
53723
53724
53725
53726
53727 protected function configure()
53728 {
53729 }
53730
53731
53732
53733
53734
53735
53736
53737
53738
53739
53740
53741
53742
53743
53744
53745 protected function execute(InputInterface $input, OutputInterface $output)
53746 {
53747 throw new LogicException('You must override the execute() method in the concrete command class.');
53748 }
53749
53750
53751
53752
53753
53754
53755
53756
53757 protected function interact(InputInterface $input, OutputInterface $output)
53758 {
53759 }
53760
53761
53762
53763
53764
53765
53766
53767
53768
53769
53770
53771 protected function initialize(InputInterface $input, OutputInterface $output)
53772 {
53773 }
53774
53775
53776
53777
53778
53779
53780
53781
53782
53783
53784
53785
53786
53787
53788
53789 public function run(InputInterface $input, OutputInterface $output)
53790 {
53791
53792 $this->getSynopsis(true);
53793 $this->getSynopsis(false);
53794
53795
53796 $this->mergeApplicationDefinition();
53797
53798
53799 try {
53800 $input->bind($this->definition);
53801 } catch (ExceptionInterface $e) {
53802 if (!$this->ignoreValidationErrors) {
53803 throw $e;
53804 }
53805 }
53806
53807 $this->initialize($input, $output);
53808
53809 if (null !== $this->processTitle) {
53810 if (\function_exists('cli_set_process_title')) {
53811 if (!@cli_set_process_title($this->processTitle)) {
53812 if ('Darwin' === PHP_OS) {
53813 $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
53814 } else {
53815 cli_set_process_title($this->processTitle);
53816 }
53817 }
53818 } elseif (\function_exists('setproctitle')) {
53819 setproctitle($this->processTitle);
53820 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
53821 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
53822 }
53823 }
53824
53825 if ($input->isInteractive()) {
53826 $this->interact($input, $output);
53827 }
53828
53829
53830
53831
53832 if ($input->hasArgument('command') && null === $input->getArgument('command')) {
53833 $input->setArgument('command', $this->getName());
53834 }
53835
53836 $input->validate();
53837
53838 if ($this->code) {
53839 $statusCode = \call_user_func($this->code, $input, $output);
53840 } else {
53841 $statusCode = $this->execute($input, $output);
53842 }
53843
53844 return is_numeric($statusCode) ? (int) $statusCode : 0;
53845 }
53846
53847
53848
53849
53850
53851
53852
53853
53854
53855
53856
53857
53858
53859
53860
53861 public function setCode($code)
53862 {
53863 if (!\is_callable($code)) {
53864 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
53865 }
53866
53867 if (\PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
53868 $r = new \ReflectionFunction($code);
53869 if (null === $r->getClosureThis()) {
53870 if (\PHP_VERSION_ID < 70000) {
53871
53872
53873
53874
53875 $code = @\Closure::bind($code, $this);
53876 } else {
53877 $code = \Closure::bind($code, $this);
53878 }
53879 }
53880 }
53881
53882 $this->code = $code;
53883
53884 return $this;
53885 }
53886
53887
53888
53889
53890
53891
53892
53893
53894 public function mergeApplicationDefinition($mergeArgs = true)
53895 {
53896 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
53897 return;
53898 }
53899
53900 $this->definition->addOptions($this->application->getDefinition()->getOptions());
53901
53902 $this->applicationDefinitionMerged = true;
53903
53904 if ($mergeArgs) {
53905 $currentArguments = $this->definition->getArguments();
53906 $this->definition->setArguments($this->application->getDefinition()->getArguments());
53907 $this->definition->addArguments($currentArguments);
53908
53909 $this->applicationDefinitionMergedWithArgs = true;
53910 }
53911 }
53912
53913
53914
53915
53916
53917
53918
53919
53920 public function setDefinition($definition)
53921 {
53922 if ($definition instanceof InputDefinition) {
53923 $this->definition = $definition;
53924 } else {
53925 $this->definition->setDefinition($definition);
53926 }
53927
53928 $this->applicationDefinitionMerged = false;
53929
53930 return $this;
53931 }
53932
53933
53934
53935
53936
53937
53938 public function getDefinition()
53939 {
53940 return $this->definition;
53941 }
53942
53943
53944
53945
53946
53947
53948
53949
53950
53951
53952
53953 public function getNativeDefinition()
53954 {
53955 return $this->getDefinition();
53956 }
53957
53958
53959
53960
53961
53962
53963
53964
53965
53966
53967
53968
53969
53970 public function addArgument($name, $mode = null, $description = '', $default = null)
53971 {
53972 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
53973
53974 return $this;
53975 }
53976
53977
53978
53979
53980
53981
53982
53983
53984
53985
53986
53987
53988
53989
53990 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
53991 {
53992 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
53993
53994 return $this;
53995 }
53996
53997
53998
53999
54000
54001
54002
54003
54004
54005
54006
54007
54008
54009
54010
54011 public function setName($name)
54012 {
54013 $this->validateName($name);
54014
54015 $this->name = $name;
54016
54017 return $this;
54018 }
54019
54020
54021
54022
54023
54024
54025
54026
54027
54028
54029
54030
54031
54032 public function setProcessTitle($title)
54033 {
54034 $this->processTitle = $title;
54035
54036 return $this;
54037 }
54038
54039
54040
54041
54042
54043
54044 public function getName()
54045 {
54046 return $this->name;
54047 }
54048
54049
54050
54051
54052
54053
54054
54055
54056 public function setDescription($description)
54057 {
54058 $this->description = $description;
54059
54060 return $this;
54061 }
54062
54063
54064
54065
54066
54067
54068 public function getDescription()
54069 {
54070 return $this->description;
54071 }
54072
54073
54074
54075
54076
54077
54078
54079
54080 public function setHelp($help)
54081 {
54082 $this->help = $help;
54083
54084 return $this;
54085 }
54086
54087
54088
54089
54090
54091
54092 public function getHelp()
54093 {
54094 return $this->help;
54095 }
54096
54097
54098
54099
54100
54101
54102
54103 public function getProcessedHelp()
54104 {
54105 $name = $this->name;
54106
54107 $placeholders = array(
54108 '%command.name%',
54109 '%command.full_name%',
54110 );
54111 $replacements = array(
54112 $name,
54113 $_SERVER['PHP_SELF'].' '.$name,
54114 );
54115
54116 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
54117 }
54118
54119
54120
54121
54122
54123
54124
54125
54126
54127
54128 public function setAliases($aliases)
54129 {
54130 if (!\is_array($aliases) && !$aliases instanceof \Traversable) {
54131 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
54132 }
54133
54134 foreach ($aliases as $alias) {
54135 $this->validateName($alias);
54136 }
54137
54138 $this->aliases = $aliases;
54139
54140 return $this;
54141 }
54142
54143
54144
54145
54146
54147
54148 public function getAliases()
54149 {
54150 return $this->aliases;
54151 }
54152
54153
54154
54155
54156
54157
54158
54159
54160 public function getSynopsis($short = false)
54161 {
54162 $key = $short ? 'short' : 'long';
54163
54164 if (!isset($this->synopsis[$key])) {
54165 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
54166 }
54167
54168 return $this->synopsis[$key];
54169 }
54170
54171
54172
54173
54174
54175
54176
54177
54178 public function addUsage($usage)
54179 {
54180 if (0 !== strpos($usage, $this->name)) {
54181 $usage = sprintf('%s %s', $this->name, $usage);
54182 }
54183
54184 $this->usages[] = $usage;
54185
54186 return $this;
54187 }
54188
54189
54190
54191
54192
54193
54194 public function getUsages()
54195 {
54196 return $this->usages;
54197 }
54198
54199
54200
54201
54202
54203
54204
54205
54206
54207
54208
54209 public function getHelper($name)
54210 {
54211 if (null === $this->helperSet) {
54212 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));
54213 }
54214
54215 return $this->helperSet->get($name);
54216 }
54217
54218
54219
54220
54221
54222
54223
54224
54225 public function asText()
54226 {
54227 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
54228
54229 $descriptor = new TextDescriptor();
54230 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
54231 $descriptor->describe($output, $this, array('raw_output' => true));
54232
54233 return $output->fetch();
54234 }
54235
54236
54237
54238
54239
54240
54241
54242
54243
54244
54245 public function asXml($asDom = false)
54246 {
54247 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
54248
54249 $descriptor = new XmlDescriptor();
54250
54251 if ($asDom) {
54252 return $descriptor->getCommandDocument($this);
54253 }
54254
54255 $output = new BufferedOutput();
54256 $descriptor->describe($output, $this);
54257
54258 return $output->fetch();
54259 }
54260
54261
54262
54263
54264
54265
54266
54267
54268
54269
54270 private function validateName($name)
54271 {
54272 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
54273 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
54274 }
54275 }
54276 }
54277 <?php
54278
54279
54280
54281
54282
54283
54284
54285
54286
54287
54288 namespace Symfony\Component\Console\Command;
54289
54290 use Symfony\Component\Console\Helper\DescriptorHelper;
54291 use Symfony\Component\Console\Input\InputArgument;
54292 use Symfony\Component\Console\Input\InputInterface;
54293 use Symfony\Component\Console\Input\InputOption;
54294 use Symfony\Component\Console\Output\OutputInterface;
54295
54296
54297
54298
54299
54300
54301 class HelpCommand extends Command
54302 {
54303 private $command;
54304
54305
54306
54307
54308 protected function configure()
54309 {
54310 $this->ignoreValidationErrors();
54311
54312 $this
54313 ->setName('help')
54314 ->setDefinition(array(
54315 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
54316 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
54317 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
54318 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
54319 ))
54320 ->setDescription('Displays help for a command')
54321 ->setHelp(<<<'EOF'
54322 The <info>%command.name%</info> command displays help for a given command:
54323
54324   <info>php %command.full_name% list</info>
54325
54326 You can also output the help in other formats by using the <comment>--format</comment> option:
54327
54328   <info>php %command.full_name% --format=xml list</info>
54329
54330 To display the list of available commands, please use the <info>list</info> command.
54331 EOF
54332 )
54333 ;
54334 }
54335
54336 public function setCommand(Command $command)
54337 {
54338 $this->command = $command;
54339 }
54340
54341
54342
54343
54344 protected function execute(InputInterface $input, OutputInterface $output)
54345 {
54346 if (null === $this->command) {
54347 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
54348 }
54349
54350 if ($input->getOption('xml')) {
54351 @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);
54352
54353 $input->setOption('format', 'xml');
54354 }
54355
54356 $helper = new DescriptorHelper();
54357 $helper->describe($output, $this->command, array(
54358 'format' => $input->getOption('format'),
54359 'raw_text' => $input->getOption('raw'),
54360 ));
54361
54362 $this->command = null;
54363 }
54364 }
54365 <?php
54366
54367
54368
54369
54370
54371
54372
54373
54374
54375
54376 namespace Symfony\Component\Console\Command;
54377
54378 use Symfony\Component\Console\Helper\DescriptorHelper;
54379 use Symfony\Component\Console\Input\InputArgument;
54380 use Symfony\Component\Console\Input\InputDefinition;
54381 use Symfony\Component\Console\Input\InputInterface;
54382 use Symfony\Component\Console\Input\InputOption;
54383 use Symfony\Component\Console\Output\OutputInterface;
54384
54385
54386
54387
54388
54389
54390 class ListCommand extends Command
54391 {
54392
54393
54394
54395 protected function configure()
54396 {
54397 $this
54398 ->setName('list')
54399 ->setDefinition($this->createDefinition())
54400 ->setDescription('Lists commands')
54401 ->setHelp(<<<'EOF'
54402 The <info>%command.name%</info> command lists all commands:
54403
54404   <info>php %command.full_name%</info>
54405
54406 You can also display the commands for a specific namespace:
54407
54408   <info>php %command.full_name% test</info>
54409
54410 You can also output the information in other formats by using the <comment>--format</comment> option:
54411
54412   <info>php %command.full_name% --format=xml</info>
54413
54414 It's also possible to get raw list of commands (useful for embedding command runner):
54415
54416   <info>php %command.full_name% --raw</info>
54417 EOF
54418 )
54419 ;
54420 }
54421
54422
54423
54424
54425 public function getNativeDefinition()
54426 {
54427 return $this->createDefinition();
54428 }
54429
54430
54431
54432
54433 protected function execute(InputInterface $input, OutputInterface $output)
54434 {
54435 if ($input->getOption('xml')) {
54436 @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);
54437
54438 $input->setOption('format', 'xml');
54439 }
54440
54441 $helper = new DescriptorHelper();
54442 $helper->describe($output, $this->getApplication(), array(
54443 'format' => $input->getOption('format'),
54444 'raw_text' => $input->getOption('raw'),
54445 'namespace' => $input->getArgument('namespace'),
54446 ));
54447 }
54448
54449
54450
54451
54452 private function createDefinition()
54453 {
54454 return new InputDefinition(array(
54455 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
54456 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
54457 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
54458 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
54459 ));
54460 }
54461 }
54462 <?php
54463
54464
54465
54466
54467
54468
54469
54470
54471
54472
54473 namespace Symfony\Component\Console;
54474
54475
54476
54477
54478
54479
54480 final class ConsoleEvents
54481 {
54482
54483
54484
54485
54486
54487
54488
54489
54490
54491
54492 const COMMAND = 'console.command';
54493
54494
54495
54496
54497
54498
54499
54500
54501
54502
54503 const TERMINATE = 'console.terminate';
54504
54505
54506
54507
54508
54509
54510
54511
54512
54513
54514
54515 const EXCEPTION = 'console.exception';
54516 }
54517 <?php
54518
54519
54520
54521
54522
54523
54524
54525
54526
54527
54528 namespace Symfony\Component\Console\Descriptor;
54529
54530 use Symfony\Component\Console\Application;
54531 use Symfony\Component\Console\Command\Command;
54532 use Symfony\Component\Console\Exception\CommandNotFoundException;
54533
54534
54535
54536
54537
54538
54539 class ApplicationDescription
54540 {
54541 const GLOBAL_NAMESPACE = '_global';
54542
54543 private $application;
54544 private $namespace;
54545
54546
54547
54548
54549 private $namespaces;
54550
54551
54552
54553
54554 private $commands;
54555
54556
54557
54558
54559 private $aliases;
54560
54561 public function __construct(Application $application, $namespace = null)
54562 {
54563 $this->application = $application;
54564 $this->namespace = $namespace;
54565 }
54566
54567
54568
54569
54570 public function getNamespaces()
54571 {
54572 if (null === $this->namespaces) {
54573 $this->inspectApplication();
54574 }
54575
54576 return $this->namespaces;
54577 }
54578
54579
54580
54581
54582 public function getCommands()
54583 {
54584 if (null === $this->commands) {
54585 $this->inspectApplication();
54586 }
54587
54588 return $this->commands;
54589 }
54590
54591
54592
54593
54594
54595
54596
54597
54598 public function getCommand($name)
54599 {
54600 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
54601 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
54602 }
54603
54604 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
54605 }
54606
54607 private function inspectApplication()
54608 {
54609 $this->commands = array();
54610 $this->namespaces = array();
54611
54612 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
54613 foreach ($this->sortCommands($all) as $namespace => $commands) {
54614 $names = array();
54615
54616
54617 foreach ($commands as $name => $command) {
54618 if (!$command->getName()) {
54619 continue;
54620 }
54621
54622 if ($command->getName() === $name) {
54623 $this->commands[$name] = $command;
54624 } else {
54625 $this->aliases[$name] = $command;
54626 }
54627
54628 $names[] = $name;
54629 }
54630
54631 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
54632 }
54633 }
54634
54635
54636
54637
54638 private function sortCommands(array $commands)
54639 {
54640 $namespacedCommands = array();
54641 $globalCommands = array();
54642 foreach ($commands as $name => $command) {
54643 $key = $this->application->extractNamespace($name, 1);
54644 if (!$key) {
54645 $globalCommands['_global'][$name] = $command;
54646 } else {
54647 $namespacedCommands[$key][$name] = $command;
54648 }
54649 }
54650 ksort($namespacedCommands);
54651 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
54652
54653 foreach ($namespacedCommands as &$commandsSet) {
54654 ksort($commandsSet);
54655 }
54656
54657 unset($commandsSet);
54658
54659 return $namespacedCommands;
54660 }
54661 }
54662 <?php
54663
54664
54665
54666
54667
54668
54669
54670
54671
54672
54673 namespace Symfony\Component\Console\Descriptor;
54674
54675 use Symfony\Component\Console\Application;
54676 use Symfony\Component\Console\Command\Command;
54677 use Symfony\Component\Console\Exception\InvalidArgumentException;
54678 use Symfony\Component\Console\Input\InputArgument;
54679 use Symfony\Component\Console\Input\InputDefinition;
54680 use Symfony\Component\Console\Input\InputOption;
54681 use Symfony\Component\Console\Output\OutputInterface;
54682
54683
54684
54685
54686
54687
54688 abstract class Descriptor implements DescriptorInterface
54689 {
54690
54691
54692
54693 private $output;
54694
54695
54696
54697
54698 public function describe(OutputInterface $output, $object, array $options = array())
54699 {
54700 $this->output = $output;
54701
54702 switch (true) {
54703 case $object instanceof InputArgument:
54704 $this->describeInputArgument($object, $options);
54705 break;
54706 case $object instanceof InputOption:
54707 $this->describeInputOption($object, $options);
54708 break;
54709 case $object instanceof InputDefinition:
54710 $this->describeInputDefinition($object, $options);
54711 break;
54712 case $object instanceof Command:
54713 $this->describeCommand($object, $options);
54714 break;
54715 case $object instanceof Application:
54716 $this->describeApplication($object, $options);
54717 break;
54718 default:
54719 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object)));
54720 }
54721 }
54722
54723
54724
54725
54726
54727
54728
54729 protected function write($content, $decorated = false)
54730 {
54731 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
54732 }
54733
54734
54735
54736
54737
54738
54739 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
54740
54741
54742
54743
54744
54745
54746 abstract protected function describeInputOption(InputOption $option, array $options = array());
54747
54748
54749
54750
54751
54752
54753 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
54754
54755
54756
54757
54758
54759
54760 abstract protected function describeCommand(Command $command, array $options = array());
54761
54762
54763
54764
54765
54766
54767 abstract protected function describeApplication(Application $application, array $options = array());
54768 }
54769 <?php
54770
54771
54772
54773
54774
54775
54776
54777
54778
54779
54780 namespace Symfony\Component\Console\Descriptor;
54781
54782 use Symfony\Component\Console\Output\OutputInterface;
54783
54784
54785
54786
54787
54788
54789 interface DescriptorInterface
54790 {
54791
54792
54793
54794
54795
54796
54797
54798 public function describe(OutputInterface $output, $object, array $options = array());
54799 }
54800 <?php
54801
54802
54803
54804
54805
54806
54807
54808
54809
54810
54811 namespace Symfony\Component\Console\Descriptor;
54812
54813 use Symfony\Component\Console\Application;
54814 use Symfony\Component\Console\Command\Command;
54815 use Symfony\Component\Console\Input\InputArgument;
54816 use Symfony\Component\Console\Input\InputDefinition;
54817 use Symfony\Component\Console\Input\InputOption;
54818
54819
54820
54821
54822
54823
54824
54825
54826 class JsonDescriptor extends Descriptor
54827 {
54828
54829
54830
54831 protected function describeInputArgument(InputArgument $argument, array $options = array())
54832 {
54833 $this->writeData($this->getInputArgumentData($argument), $options);
54834 }
54835
54836
54837
54838
54839 protected function describeInputOption(InputOption $option, array $options = array())
54840 {
54841 $this->writeData($this->getInputOptionData($option), $options);
54842 }
54843
54844
54845
54846
54847 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
54848 {
54849 $this->writeData($this->getInputDefinitionData($definition), $options);
54850 }
54851
54852
54853
54854
54855 protected function describeCommand(Command $command, array $options = array())
54856 {
54857 $this->writeData($this->getCommandData($command), $options);
54858 }
54859
54860
54861
54862
54863 protected function describeApplication(Application $application, array $options = array())
54864 {
54865 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
54866 $description = new ApplicationDescription($application, $describedNamespace);
54867 $commands = array();
54868
54869 foreach ($description->getCommands() as $command) {
54870 $commands[] = $this->getCommandData($command);
54871 }
54872
54873 $data = $describedNamespace
54874 ? array('commands' => $commands, 'namespace' => $describedNamespace)
54875 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
54876
54877 $this->writeData($data, $options);
54878 }
54879
54880
54881
54882
54883
54884
54885 private function writeData(array $data, array $options)
54886 {
54887 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
54888 }
54889
54890
54891
54892
54893 private function getInputArgumentData(InputArgument $argument)
54894 {
54895 return array(
54896 'name' => $argument->getName(),
54897 'is_required' => $argument->isRequired(),
54898 'is_array' => $argument->isArray(),
54899 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
54900 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
54901 );
54902 }
54903
54904
54905
54906
54907 private function getInputOptionData(InputOption $option)
54908 {
54909 return array(
54910 'name' => '--'.$option->getName(),
54911 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
54912 'accept_value' => $option->acceptValue(),
54913 'is_value_required' => $option->isValueRequired(),
54914 'is_multiple' => $option->isArray(),
54915 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
54916 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
54917 );
54918 }
54919
54920
54921
54922
54923 private function getInputDefinitionData(InputDefinition $definition)
54924 {
54925 $inputArguments = array();
54926 foreach ($definition->getArguments() as $name => $argument) {
54927 $inputArguments[$name] = $this->getInputArgumentData($argument);
54928 }
54929
54930 $inputOptions = array();
54931 foreach ($definition->getOptions() as $name => $option) {
54932 $inputOptions[$name] = $this->getInputOptionData($option);
54933 }
54934
54935 return array('arguments' => $inputArguments, 'options' => $inputOptions);
54936 }
54937
54938
54939
54940
54941 private function getCommandData(Command $command)
54942 {
54943 $command->getSynopsis();
54944 $command->mergeApplicationDefinition(false);
54945
54946 return array(
54947 'name' => $command->getName(),
54948 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
54949 'description' => $command->getDescription(),
54950 'help' => $command->getProcessedHelp(),
54951 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
54952 );
54953 }
54954 }
54955 <?php
54956
54957
54958
54959
54960
54961
54962
54963
54964
54965
54966 namespace Symfony\Component\Console\Descriptor;
54967
54968 use Symfony\Component\Console\Application;
54969 use Symfony\Component\Console\Command\Command;
54970 use Symfony\Component\Console\Helper\Helper;
54971 use Symfony\Component\Console\Input\InputArgument;
54972 use Symfony\Component\Console\Input\InputDefinition;
54973 use Symfony\Component\Console\Input\InputOption;
54974
54975
54976
54977
54978
54979
54980
54981
54982 class MarkdownDescriptor extends Descriptor
54983 {
54984
54985
54986
54987 protected function describeInputArgument(InputArgument $argument, array $options = array())
54988 {
54989 $this->write(
54990 '**'.$argument->getName().':**'."\n\n"
54991 .'* Name: '.($argument->getName() ?: '<none>')."\n"
54992 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
54993 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
54994 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
54995 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
54996 );
54997 }
54998
54999
55000
55001
55002 protected function describeInputOption(InputOption $option, array $options = array())
55003 {
55004 $this->write(
55005 '**'.$option->getName().':**'."\n\n"
55006 .'* Name: `--'.$option->getName().'`'."\n"
55007 .'* Shortcut: '.($option->getShortcut() ? '`-'.str_replace('|', '|-', $option->getShortcut()).'`' : '<none>')."\n"
55008 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
55009 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
55010 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
55011 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
55012 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
55013 );
55014 }
55015
55016
55017
55018
55019 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
55020 {
55021 if ($showArguments = \count($definition->getArguments()) > 0) {
55022 $this->write('### Arguments:');
55023 foreach ($definition->getArguments() as $argument) {
55024 $this->write("\n\n");
55025 $this->write($this->describeInputArgument($argument));
55026 }
55027 }
55028
55029 if (\count($definition->getOptions()) > 0) {
55030 if ($showArguments) {
55031 $this->write("\n\n");
55032 }
55033
55034 $this->write('### Options:');
55035 foreach ($definition->getOptions() as $option) {
55036 $this->write("\n\n");
55037 $this->write($this->describeInputOption($option));
55038 }
55039 }
55040 }
55041
55042
55043
55044
55045 protected function describeCommand(Command $command, array $options = array())
55046 {
55047 $command->getSynopsis();
55048 $command->mergeApplicationDefinition(false);
55049
55050 $this->write(
55051 $command->getName()."\n"
55052 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
55053 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
55054 .'* Usage:'."\n\n"
55055 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
55056 return $carry.'  * `'.$usage.'`'."\n";
55057 })
55058 );
55059
55060 if ($help = $command->getProcessedHelp()) {
55061 $this->write("\n");
55062 $this->write($help);
55063 }
55064
55065 if ($command->getNativeDefinition()) {
55066 $this->write("\n\n");
55067 $this->describeInputDefinition($command->getNativeDefinition());
55068 }
55069 }
55070
55071
55072
55073
55074 protected function describeApplication(Application $application, array $options = array())
55075 {
55076 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
55077 $description = new ApplicationDescription($application, $describedNamespace);
55078
55079 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
55080
55081 foreach ($description->getNamespaces() as $namespace) {
55082 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
55083 $this->write("\n\n");
55084 $this->write('**'.$namespace['id'].':**');
55085 }
55086
55087 $this->write("\n\n");
55088 $this->write(implode("\n", array_map(function ($commandName) {
55089 return '* '.$commandName;
55090 }, $namespace['commands'])));
55091 }
55092
55093 foreach ($description->getCommands() as $command) {
55094 $this->write("\n\n");
55095 $this->write($this->describeCommand($command));
55096 }
55097 }
55098 }
55099 <?php
55100
55101
55102
55103
55104
55105
55106
55107
55108
55109
55110 namespace Symfony\Component\Console\Descriptor;
55111
55112 use Symfony\Component\Console\Application;
55113 use Symfony\Component\Console\Command\Command;
55114 use Symfony\Component\Console\Formatter\OutputFormatter;
55115 use Symfony\Component\Console\Helper\Helper;
55116 use Symfony\Component\Console\Input\InputArgument;
55117 use Symfony\Component\Console\Input\InputDefinition;
55118 use Symfony\Component\Console\Input\InputOption;
55119
55120
55121
55122
55123
55124
55125
55126
55127 class TextDescriptor extends Descriptor
55128 {
55129
55130
55131
55132 protected function describeInputArgument(InputArgument $argument, array $options = array())
55133 {
55134 if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
55135 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
55136 } else {
55137 $default = '';
55138 }
55139
55140 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
55141 $spacingWidth = $totalWidth - \strlen($argument->getName());
55142
55143 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
55144 $argument->getName(),
55145 str_repeat(' ', $spacingWidth),
55146
55147 preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
55148 $default
55149 ), $options);
55150 }
55151
55152
55153
55154
55155 protected function describeInputOption(InputOption $option, array $options = array())
55156 {
55157 if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
55158 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
55159 } else {
55160 $default = '';
55161 }
55162
55163 $value = '';
55164 if ($option->acceptValue()) {
55165 $value = '='.strtoupper($option->getName());
55166
55167 if ($option->isValueOptional()) {
55168 $value = '['.$value.']';
55169 }
55170 }
55171
55172 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
55173 $synopsis = sprintf('%s%s',
55174 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
55175 sprintf('--%s%s', $option->getName(), $value)
55176 );
55177
55178 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
55179
55180 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
55181 $synopsis,
55182 str_repeat(' ', $spacingWidth),
55183
55184 preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
55185 $default,
55186 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
55187 ), $options);
55188 }
55189
55190
55191
55192
55193 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
55194 {
55195 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
55196 foreach ($definition->getArguments() as $argument) {
55197 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
55198 }
55199
55200 if ($definition->getArguments()) {
55201 $this->writeText('<comment>Arguments:</comment>', $options);
55202 $this->writeText("\n");
55203 foreach ($definition->getArguments() as $argument) {
55204 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
55205 $this->writeText("\n");
55206 }
55207 }
55208
55209 if ($definition->getArguments() && $definition->getOptions()) {
55210 $this->writeText("\n");
55211 }
55212
55213 if ($definition->getOptions()) {
55214 $laterOptions = array();
55215
55216 $this->writeText('<comment>Options:</comment>', $options);
55217 foreach ($definition->getOptions() as $option) {
55218 if (\strlen($option->getShortcut()) > 1) {
55219 $laterOptions[] = $option;
55220 continue;
55221 }
55222 $this->writeText("\n");
55223 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
55224 }
55225 foreach ($laterOptions as $option) {
55226 $this->writeText("\n");
55227 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
55228 }
55229 }
55230 }
55231
55232
55233
55234
55235 protected function describeCommand(Command $command, array $options = array())
55236 {
55237 $command->getSynopsis(true);
55238 $command->getSynopsis(false);
55239 $command->mergeApplicationDefinition(false);
55240
55241 $this->writeText('<comment>Usage:</comment>', $options);
55242 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
55243 $this->writeText("\n");
55244 $this->writeText('  '.OutputFormatter::escape($usage), $options);
55245 }
55246 $this->writeText("\n");
55247
55248 $definition = $command->getNativeDefinition();
55249 if ($definition->getOptions() || $definition->getArguments()) {
55250 $this->writeText("\n");
55251 $this->describeInputDefinition($definition, $options);
55252 $this->writeText("\n");
55253 }
55254
55255 if ($help = $command->getProcessedHelp()) {
55256 $this->writeText("\n");
55257 $this->writeText('<comment>Help:</comment>', $options);
55258 $this->writeText("\n");
55259 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
55260 $this->writeText("\n");
55261 }
55262 }
55263
55264
55265
55266
55267 protected function describeApplication(Application $application, array $options = array())
55268 {
55269 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
55270 $description = new ApplicationDescription($application, $describedNamespace);
55271
55272 if (isset($options['raw_text']) && $options['raw_text']) {
55273 $width = $this->getColumnWidth($description->getCommands());
55274
55275 foreach ($description->getCommands() as $command) {
55276 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
55277 $this->writeText("\n");
55278 }
55279 } else {
55280 if ('' != $help = $application->getHelp()) {
55281 $this->writeText("$help\n\n", $options);
55282 }
55283
55284 $this->writeText("<comment>Usage:</comment>\n", $options);
55285 $this->writeText("  command [options] [arguments]\n\n", $options);
55286
55287 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
55288
55289 $this->writeText("\n");
55290 $this->writeText("\n");
55291
55292 $width = $this->getColumnWidth($description->getCommands());
55293
55294 if ($describedNamespace) {
55295 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
55296 } else {
55297 $this->writeText('<comment>Available commands:</comment>', $options);
55298 }
55299
55300
55301 foreach ($description->getNamespaces() as $namespace) {
55302 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
55303 $this->writeText("\n");
55304 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
55305 }
55306
55307 foreach ($namespace['commands'] as $name) {
55308 $this->writeText("\n");
55309 $spacingWidth = $width - Helper::strlen($name);
55310 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
55311 }
55312 }
55313
55314 $this->writeText("\n");
55315 }
55316 }
55317
55318
55319
55320
55321 private function writeText($content, array $options = array())
55322 {
55323 $this->write(
55324 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
55325 isset($options['raw_output']) ? !$options['raw_output'] : true
55326 );
55327 }
55328
55329
55330
55331
55332
55333
55334
55335
55336 private function formatDefaultValue($default)
55337 {
55338 if (INF === $default) {
55339 return 'INF';
55340 }
55341
55342 if (\is_string($default)) {
55343 $default = OutputFormatter::escape($default);
55344 } elseif (\is_array($default)) {
55345 foreach ($default as $key => $value) {
55346 if (\is_string($value)) {
55347 $default[$key] = OutputFormatter::escape($value);
55348 }
55349 }
55350 }
55351
55352 if (\PHP_VERSION_ID < 50400) {
55353 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
55354 }
55355
55356 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
55357 }
55358
55359
55360
55361
55362
55363
55364 private function getColumnWidth(array $commands)
55365 {
55366 $widths = array();
55367
55368 foreach ($commands as $command) {
55369 $widths[] = Helper::strlen($command->getName());
55370 foreach ($command->getAliases() as $alias) {
55371 $widths[] = Helper::strlen($alias);
55372 }
55373 }
55374
55375 return max($widths) + 2;
55376 }
55377
55378
55379
55380
55381
55382
55383 private function calculateTotalWidthForOptions(array $options)
55384 {
55385 $totalWidth = 0;
55386 foreach ($options as $option) {
55387
55388 $nameLength = 1 + max(\strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
55389
55390 if ($option->acceptValue()) {
55391 $valueLength = 1 + Helper::strlen($option->getName()); 
55392 $valueLength += $option->isValueOptional() ? 2 : 0; 
55393
55394 $nameLength += $valueLength;
55395 }
55396 $totalWidth = max($totalWidth, $nameLength);
55397 }
55398
55399 return $totalWidth;
55400 }
55401 }
55402 <?php
55403
55404
55405
55406
55407
55408
55409
55410
55411
55412
55413 namespace Symfony\Component\Console\Descriptor;
55414
55415 use Symfony\Component\Console\Application;
55416 use Symfony\Component\Console\Command\Command;
55417 use Symfony\Component\Console\Input\InputArgument;
55418 use Symfony\Component\Console\Input\InputDefinition;
55419 use Symfony\Component\Console\Input\InputOption;
55420
55421
55422
55423
55424
55425
55426
55427
55428 class XmlDescriptor extends Descriptor
55429 {
55430
55431
55432
55433 public function getInputDefinitionDocument(InputDefinition $definition)
55434 {
55435 $dom = new \DOMDocument('1.0', 'UTF-8');
55436 $dom->appendChild($definitionXML = $dom->createElement('definition'));
55437
55438 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
55439 foreach ($definition->getArguments() as $argument) {
55440 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
55441 }
55442
55443 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
55444 foreach ($definition->getOptions() as $option) {
55445 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
55446 }
55447
55448 return $dom;
55449 }
55450
55451
55452
55453
55454 public function getCommandDocument(Command $command)
55455 {
55456 $dom = new \DOMDocument('1.0', 'UTF-8');
55457 $dom->appendChild($commandXML = $dom->createElement('command'));
55458
55459 $command->getSynopsis();
55460 $command->mergeApplicationDefinition(false);
55461
55462 $commandXML->setAttribute('id', $command->getName());
55463 $commandXML->setAttribute('name', $command->getName());
55464
55465 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
55466
55467 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
55468 $usagesXML->appendChild($dom->createElement('usage', $usage));
55469 }
55470
55471 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
55472 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
55473
55474 $commandXML->appendChild($helpXML = $dom->createElement('help'));
55475 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
55476
55477 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
55478 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
55479
55480 return $dom;
55481 }
55482
55483
55484
55485
55486
55487
55488
55489 public function getApplicationDocument(Application $application, $namespace = null)
55490 {
55491 $dom = new \DOMDocument('1.0', 'UTF-8');
55492 $dom->appendChild($rootXml = $dom->createElement('symfony'));
55493
55494 if ('UNKNOWN' !== $application->getName()) {
55495 $rootXml->setAttribute('name', $application->getName());
55496 if ('UNKNOWN' !== $application->getVersion()) {
55497 $rootXml->setAttribute('version', $application->getVersion());
55498 }
55499 }
55500
55501 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
55502
55503 $description = new ApplicationDescription($application, $namespace);
55504
55505 if ($namespace) {
55506 $commandsXML->setAttribute('namespace', $namespace);
55507 }
55508
55509 foreach ($description->getCommands() as $command) {
55510 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
55511 }
55512
55513 if (!$namespace) {
55514 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
55515
55516 foreach ($description->getNamespaces() as $namespaceDescription) {
55517 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
55518 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
55519
55520 foreach ($namespaceDescription['commands'] as $name) {
55521 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
55522 $commandXML->appendChild($dom->createTextNode($name));
55523 }
55524 }
55525 }
55526
55527 return $dom;
55528 }
55529
55530
55531
55532
55533 protected function describeInputArgument(InputArgument $argument, array $options = array())
55534 {
55535 $this->writeDocument($this->getInputArgumentDocument($argument));
55536 }
55537
55538
55539
55540
55541 protected function describeInputOption(InputOption $option, array $options = array())
55542 {
55543 $this->writeDocument($this->getInputOptionDocument($option));
55544 }
55545
55546
55547
55548
55549 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
55550 {
55551 $this->writeDocument($this->getInputDefinitionDocument($definition));
55552 }
55553
55554
55555
55556
55557 protected function describeCommand(Command $command, array $options = array())
55558 {
55559 $this->writeDocument($this->getCommandDocument($command));
55560 }
55561
55562
55563
55564
55565 protected function describeApplication(Application $application, array $options = array())
55566 {
55567 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
55568 }
55569
55570
55571
55572
55573 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
55574 {
55575 foreach ($importedParent->childNodes as $childNode) {
55576 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
55577 }
55578 }
55579
55580
55581
55582
55583
55584
55585 private function writeDocument(\DOMDocument $dom)
55586 {
55587 $dom->formatOutput = true;
55588 $this->write($dom->saveXML());
55589 }
55590
55591
55592
55593
55594 private function getInputArgumentDocument(InputArgument $argument)
55595 {
55596 $dom = new \DOMDocument('1.0', 'UTF-8');
55597
55598 $dom->appendChild($objectXML = $dom->createElement('argument'));
55599 $objectXML->setAttribute('name', $argument->getName());
55600 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
55601 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
55602 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
55603 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
55604
55605 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
55606 $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
55607 foreach ($defaults as $default) {
55608 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
55609 $defaultXML->appendChild($dom->createTextNode($default));
55610 }
55611
55612 return $dom;
55613 }
55614
55615
55616
55617
55618 private function getInputOptionDocument(InputOption $option)
55619 {
55620 $dom = new \DOMDocument('1.0', 'UTF-8');
55621
55622 $dom->appendChild($objectXML = $dom->createElement('option'));
55623 $objectXML->setAttribute('name', '--'.$option->getName());
55624 $pos = strpos($option->getShortcut(), '|');
55625 if (false !== $pos) {
55626 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
55627 $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
55628 } else {
55629 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
55630 }
55631 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
55632 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
55633 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
55634 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
55635 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
55636
55637 if ($option->acceptValue()) {
55638 $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
55639 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
55640
55641 if (!empty($defaults)) {
55642 foreach ($defaults as $default) {
55643 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
55644 $defaultXML->appendChild($dom->createTextNode($default));
55645 }
55646 }
55647 }
55648
55649 return $dom;
55650 }
55651 }
55652 <?php
55653
55654
55655
55656
55657
55658
55659
55660
55661
55662
55663 namespace Symfony\Component\Console\Event;
55664
55665
55666
55667
55668
55669
55670 class ConsoleCommandEvent extends ConsoleEvent
55671 {
55672
55673
55674
55675 const RETURN_CODE_DISABLED = 113;
55676
55677
55678
55679
55680 private $commandShouldRun = true;
55681
55682
55683
55684
55685
55686
55687 public function disableCommand()
55688 {
55689 return $this->commandShouldRun = false;
55690 }
55691
55692
55693
55694
55695
55696
55697 public function enableCommand()
55698 {
55699 return $this->commandShouldRun = true;
55700 }
55701
55702
55703
55704
55705
55706
55707 public function commandShouldRun()
55708 {
55709 return $this->commandShouldRun;
55710 }
55711 }
55712 <?php
55713
55714
55715
55716
55717
55718
55719
55720
55721
55722
55723 namespace Symfony\Component\Console\Event;
55724
55725 use Symfony\Component\Console\Command\Command;
55726 use Symfony\Component\Console\Input\InputInterface;
55727 use Symfony\Component\Console\Output\OutputInterface;
55728 use Symfony\Component\EventDispatcher\Event;
55729
55730
55731
55732
55733
55734
55735 class ConsoleEvent extends Event
55736 {
55737 protected $command;
55738
55739 private $input;
55740 private $output;
55741
55742 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
55743 {
55744 $this->command = $command;
55745 $this->input = $input;
55746 $this->output = $output;
55747 }
55748
55749
55750
55751
55752
55753
55754 public function getCommand()
55755 {
55756 return $this->command;
55757 }
55758
55759
55760
55761
55762
55763
55764 public function getInput()
55765 {
55766 return $this->input;
55767 }
55768
55769
55770
55771
55772
55773
55774 public function getOutput()
55775 {
55776 return $this->output;
55777 }
55778 }
55779 <?php
55780
55781
55782
55783
55784
55785
55786
55787
55788
55789
55790 namespace Symfony\Component\Console\Event;
55791
55792 use Symfony\Component\Console\Command\Command;
55793 use Symfony\Component\Console\Input\InputInterface;
55794 use Symfony\Component\Console\Output\OutputInterface;
55795
55796
55797
55798
55799
55800
55801 class ConsoleExceptionEvent extends ConsoleEvent
55802 {
55803 private $exception;
55804 private $exitCode;
55805
55806 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
55807 {
55808 parent::__construct($command, $input, $output);
55809
55810 $this->setException($exception);
55811 $this->exitCode = (int) $exitCode;
55812 }
55813
55814
55815
55816
55817
55818
55819 public function getException()
55820 {
55821 return $this->exception;
55822 }
55823
55824
55825
55826
55827
55828
55829
55830
55831 public function setException(\Exception $exception)
55832 {
55833 $this->exception = $exception;
55834 }
55835
55836
55837
55838
55839
55840
55841 public function getExitCode()
55842 {
55843 return $this->exitCode;
55844 }
55845 }
55846 <?php
55847
55848
55849
55850
55851
55852
55853
55854
55855
55856
55857 namespace Symfony\Component\Console\Event;
55858
55859 use Symfony\Component\Console\Command\Command;
55860 use Symfony\Component\Console\Input\InputInterface;
55861 use Symfony\Component\Console\Output\OutputInterface;
55862
55863
55864
55865
55866
55867
55868 class ConsoleTerminateEvent extends ConsoleEvent
55869 {
55870
55871
55872
55873
55874
55875 private $exitCode;
55876
55877 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
55878 {
55879 parent::__construct($command, $input, $output);
55880
55881 $this->setExitCode($exitCode);
55882 }
55883
55884
55885
55886
55887
55888
55889 public function setExitCode($exitCode)
55890 {
55891 $this->exitCode = (int) $exitCode;
55892 }
55893
55894
55895
55896
55897
55898
55899 public function getExitCode()
55900 {
55901 return $this->exitCode;
55902 }
55903 }
55904 <?php
55905
55906
55907
55908
55909
55910
55911
55912
55913
55914
55915 namespace Symfony\Component\Console\Exception;
55916
55917
55918
55919
55920
55921
55922 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
55923 {
55924 private $alternatives;
55925
55926
55927
55928
55929
55930
55931
55932 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
55933 {
55934 parent::__construct($message, $code, $previous);
55935
55936 $this->alternatives = $alternatives;
55937 }
55938
55939
55940
55941
55942 public function getAlternatives()
55943 {
55944 return $this->alternatives;
55945 }
55946 }
55947 <?php
55948
55949
55950
55951
55952
55953
55954
55955
55956
55957
55958 namespace Symfony\Component\Console\Exception;
55959
55960
55961
55962
55963
55964
55965 interface ExceptionInterface
55966 {
55967 }
55968 <?php
55969
55970
55971
55972
55973
55974
55975
55976
55977
55978
55979 namespace Symfony\Component\Console\Exception;
55980
55981
55982
55983
55984 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
55985 {
55986 }
55987 <?php
55988
55989
55990
55991
55992
55993
55994
55995
55996
55997
55998 namespace Symfony\Component\Console\Exception;
55999
56000
56001
56002
56003
56004
56005 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
56006 {
56007 }
56008 <?php
56009
56010
56011
56012
56013
56014
56015
56016
56017
56018
56019 namespace Symfony\Component\Console\Exception;
56020
56021
56022
56023
56024 class LogicException extends \LogicException implements ExceptionInterface
56025 {
56026 }
56027 <?php
56028
56029
56030
56031
56032
56033
56034
56035
56036
56037
56038 namespace Symfony\Component\Console\Exception;
56039
56040
56041
56042
56043 class RuntimeException extends \RuntimeException implements ExceptionInterface
56044 {
56045 }
56046 <?php
56047
56048
56049
56050
56051
56052
56053
56054
56055
56056
56057 namespace Symfony\Component\Console\Formatter;
56058
56059 use Symfony\Component\Console\Exception\InvalidArgumentException;
56060
56061
56062
56063
56064
56065
56066 class OutputFormatter implements OutputFormatterInterface
56067 {
56068 private $decorated;
56069 private $styles = array();
56070 private $styleStack;
56071
56072
56073
56074
56075
56076
56077
56078
56079 public static function escape($text)
56080 {
56081 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
56082
56083 return self::escapeTrailingBackslash($text);
56084 }
56085
56086
56087
56088
56089
56090
56091
56092
56093
56094
56095 public static function escapeTrailingBackslash($text)
56096 {
56097 if ('\\' === substr($text, -1)) {
56098 $len = \strlen($text);
56099 $text = rtrim($text, '\\');
56100 $text = str_replace("\0", '', $text);
56101 $text .= str_repeat("\0", $len - \strlen($text));
56102 }
56103
56104 return $text;
56105 }
56106
56107
56108
56109
56110
56111
56112
56113 public function __construct($decorated = false, array $styles = array())
56114 {
56115 $this->decorated = (bool) $decorated;
56116
56117 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
56118 $this->setStyle('info', new OutputFormatterStyle('green'));
56119 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
56120 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
56121
56122 foreach ($styles as $name => $style) {
56123 $this->setStyle($name, $style);
56124 }
56125
56126 $this->styleStack = new OutputFormatterStyleStack();
56127 }
56128
56129
56130
56131
56132 public function setDecorated($decorated)
56133 {
56134 $this->decorated = (bool) $decorated;
56135 }
56136
56137
56138
56139
56140 public function isDecorated()
56141 {
56142 return $this->decorated;
56143 }
56144
56145
56146
56147
56148 public function setStyle($name, OutputFormatterStyleInterface $style)
56149 {
56150 $this->styles[strtolower($name)] = $style;
56151 }
56152
56153
56154
56155
56156 public function hasStyle($name)
56157 {
56158 return isset($this->styles[strtolower($name)]);
56159 }
56160
56161
56162
56163
56164 public function getStyle($name)
56165 {
56166 if (!$this->hasStyle($name)) {
56167 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
56168 }
56169
56170 return $this->styles[strtolower($name)];
56171 }
56172
56173
56174
56175
56176 public function format($message)
56177 {
56178 $message = (string) $message;
56179 $offset = 0;
56180 $output = '';
56181 $tagRegex = '[a-z][a-z0-9_=;-]*+';
56182 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
56183 foreach ($matches[0] as $i => $match) {
56184 $pos = $match[1];
56185 $text = $match[0];
56186
56187 if (0 != $pos && '\\' == $message[$pos - 1]) {
56188 continue;
56189 }
56190
56191
56192 $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
56193 $offset = $pos + \strlen($text);
56194
56195
56196 if ($open = '/' != $text[1]) {
56197 $tag = $matches[1][$i][0];
56198 } else {
56199 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
56200 }
56201
56202 if (!$open && !$tag) {
56203
56204 $this->styleStack->pop();
56205 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
56206 $output .= $this->applyCurrentStyle($text);
56207 } elseif ($open) {
56208 $this->styleStack->push($style);
56209 } else {
56210 $this->styleStack->pop($style);
56211 }
56212 }
56213
56214 $output .= $this->applyCurrentStyle(substr($message, $offset));
56215
56216 if (false !== strpos($output, "\0")) {
56217 return strtr($output, array("\0" => '\\', '\\<' => '<'));
56218 }
56219
56220 return str_replace('\\<', '<', $output);
56221 }
56222
56223
56224
56225
56226 public function getStyleStack()
56227 {
56228 return $this->styleStack;
56229 }
56230
56231
56232
56233
56234
56235
56236
56237
56238 private function createStyleFromString($string)
56239 {
56240 if (isset($this->styles[$string])) {
56241 return $this->styles[$string];
56242 }
56243
56244 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
56245 return false;
56246 }
56247
56248 $style = new OutputFormatterStyle();
56249 foreach ($matches as $match) {
56250 array_shift($match);
56251
56252 if ('fg' == $match[0]) {
56253 $style->setForeground($match[1]);
56254 } elseif ('bg' == $match[0]) {
56255 $style->setBackground($match[1]);
56256 } else {
56257 try {
56258 $style->setOption($match[1]);
56259 } catch (\InvalidArgumentException $e) {
56260 return false;
56261 }
56262 }
56263 }
56264
56265 return $style;
56266 }
56267
56268
56269
56270
56271
56272
56273
56274
56275 private function applyCurrentStyle($text)
56276 {
56277 return $this->isDecorated() && \strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
56278 }
56279 }
56280 <?php
56281
56282
56283
56284
56285
56286
56287
56288
56289
56290
56291 namespace Symfony\Component\Console\Formatter;
56292
56293
56294
56295
56296
56297
56298 interface OutputFormatterInterface
56299 {
56300
56301
56302
56303
56304
56305 public function setDecorated($decorated);
56306
56307
56308
56309
56310
56311
56312 public function isDecorated();
56313
56314
56315
56316
56317
56318
56319
56320 public function setStyle($name, OutputFormatterStyleInterface $style);
56321
56322
56323
56324
56325
56326
56327
56328
56329 public function hasStyle($name);
56330
56331
56332
56333
56334
56335
56336
56337
56338
56339
56340 public function getStyle($name);
56341
56342
56343
56344
56345
56346
56347
56348
56349 public function format($message);
56350 }
56351 <?php
56352
56353
56354
56355
56356
56357
56358
56359
56360
56361
56362 namespace Symfony\Component\Console\Formatter;
56363
56364 use Symfony\Component\Console\Exception\InvalidArgumentException;
56365
56366
56367
56368
56369
56370
56371 class OutputFormatterStyle implements OutputFormatterStyleInterface
56372 {
56373 private static $availableForegroundColors = array(
56374 'black' => array('set' => 30, 'unset' => 39),
56375 'red' => array('set' => 31, 'unset' => 39),
56376 'green' => array('set' => 32, 'unset' => 39),
56377 'yellow' => array('set' => 33, 'unset' => 39),
56378 'blue' => array('set' => 34, 'unset' => 39),
56379 'magenta' => array('set' => 35, 'unset' => 39),
56380 'cyan' => array('set' => 36, 'unset' => 39),
56381 'white' => array('set' => 37, 'unset' => 39),
56382 'default' => array('set' => 39, 'unset' => 39),
56383 );
56384 private static $availableBackgroundColors = array(
56385 'black' => array('set' => 40, 'unset' => 49),
56386 'red' => array('set' => 41, 'unset' => 49),
56387 'green' => array('set' => 42, 'unset' => 49),
56388 'yellow' => array('set' => 43, 'unset' => 49),
56389 'blue' => array('set' => 44, 'unset' => 49),
56390 'magenta' => array('set' => 45, 'unset' => 49),
56391 'cyan' => array('set' => 46, 'unset' => 49),
56392 'white' => array('set' => 47, 'unset' => 49),
56393 'default' => array('set' => 49, 'unset' => 49),
56394 );
56395 private static $availableOptions = array(
56396 'bold' => array('set' => 1, 'unset' => 22),
56397 'underscore' => array('set' => 4, 'unset' => 24),
56398 'blink' => array('set' => 5, 'unset' => 25),
56399 'reverse' => array('set' => 7, 'unset' => 27),
56400 'conceal' => array('set' => 8, 'unset' => 28),
56401 );
56402
56403 private $foreground;
56404 private $background;
56405 private $options = array();
56406
56407
56408
56409
56410
56411
56412
56413
56414 public function __construct($foreground = null, $background = null, array $options = array())
56415 {
56416 if (null !== $foreground) {
56417 $this->setForeground($foreground);
56418 }
56419 if (null !== $background) {
56420 $this->setBackground($background);
56421 }
56422 if (\count($options)) {
56423 $this->setOptions($options);
56424 }
56425 }
56426
56427
56428
56429
56430
56431
56432
56433
56434 public function setForeground($color = null)
56435 {
56436 if (null === $color) {
56437 $this->foreground = null;
56438
56439 return;
56440 }
56441
56442 if (!isset(static::$availableForegroundColors[$color])) {
56443 throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors))));
56444 }
56445
56446 $this->foreground = static::$availableForegroundColors[$color];
56447 }
56448
56449
56450
56451
56452
56453
56454
56455
56456 public function setBackground($color = null)
56457 {
56458 if (null === $color) {
56459 $this->background = null;
56460
56461 return;
56462 }
56463
56464 if (!isset(static::$availableBackgroundColors[$color])) {
56465 throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors))));
56466 }
56467
56468 $this->background = static::$availableBackgroundColors[$color];
56469 }
56470
56471
56472
56473
56474
56475
56476
56477
56478 public function setOption($option)
56479 {
56480 if (!isset(static::$availableOptions[$option])) {
56481 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
56482 }
56483
56484 if (!\in_array(static::$availableOptions[$option], $this->options)) {
56485 $this->options[] = static::$availableOptions[$option];
56486 }
56487 }
56488
56489
56490
56491
56492
56493
56494
56495
56496 public function unsetOption($option)
56497 {
56498 if (!isset(static::$availableOptions[$option])) {
56499 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
56500 }
56501
56502 $pos = array_search(static::$availableOptions[$option], $this->options);
56503 if (false !== $pos) {
56504 unset($this->options[$pos]);
56505 }
56506 }
56507
56508
56509
56510
56511 public function setOptions(array $options)
56512 {
56513 $this->options = array();
56514
56515 foreach ($options as $option) {
56516 $this->setOption($option);
56517 }
56518 }
56519
56520
56521
56522
56523
56524
56525
56526
56527 public function apply($text)
56528 {
56529 $setCodes = array();
56530 $unsetCodes = array();
56531
56532 if (null !== $this->foreground) {
56533 $setCodes[] = $this->foreground['set'];
56534 $unsetCodes[] = $this->foreground['unset'];
56535 }
56536 if (null !== $this->background) {
56537 $setCodes[] = $this->background['set'];
56538 $unsetCodes[] = $this->background['unset'];
56539 }
56540 if (\count($this->options)) {
56541 foreach ($this->options as $option) {
56542 $setCodes[] = $option['set'];
56543 $unsetCodes[] = $option['unset'];
56544 }
56545 }
56546
56547 if (0 === \count($setCodes)) {
56548 return $text;
56549 }
56550
56551 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
56552 }
56553 }
56554 <?php
56555
56556
56557
56558
56559
56560
56561
56562
56563
56564
56565 namespace Symfony\Component\Console\Formatter;
56566
56567
56568
56569
56570
56571
56572 interface OutputFormatterStyleInterface
56573 {
56574
56575
56576
56577
56578
56579 public function setForeground($color = null);
56580
56581
56582
56583
56584
56585
56586 public function setBackground($color = null);
56587
56588
56589
56590
56591
56592
56593 public function setOption($option);
56594
56595
56596
56597
56598
56599
56600 public function unsetOption($option);
56601
56602
56603
56604
56605 public function setOptions(array $options);
56606
56607
56608
56609
56610
56611
56612
56613
56614 public function apply($text);
56615 }
56616 <?php
56617
56618
56619
56620
56621
56622
56623
56624
56625
56626
56627 namespace Symfony\Component\Console\Formatter;
56628
56629 use Symfony\Component\Console\Exception\InvalidArgumentException;
56630
56631
56632
56633
56634 class OutputFormatterStyleStack
56635 {
56636
56637
56638
56639 private $styles;
56640
56641 private $emptyStyle;
56642
56643 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
56644 {
56645 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
56646 $this->reset();
56647 }
56648
56649
56650
56651
56652 public function reset()
56653 {
56654 $this->styles = array();
56655 }
56656
56657
56658
56659
56660 public function push(OutputFormatterStyleInterface $style)
56661 {
56662 $this->styles[] = $style;
56663 }
56664
56665
56666
56667
56668
56669
56670
56671
56672 public function pop(OutputFormatterStyleInterface $style = null)
56673 {
56674 if (empty($this->styles)) {
56675 return $this->emptyStyle;
56676 }
56677
56678 if (null === $style) {
56679 return array_pop($this->styles);
56680 }
56681
56682 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
56683 if ($style->apply('') === $stackedStyle->apply('')) {
56684 $this->styles = \array_slice($this->styles, 0, $index);
56685
56686 return $stackedStyle;
56687 }
56688 }
56689
56690 throw new InvalidArgumentException('Incorrectly nested style tag found.');
56691 }
56692
56693
56694
56695
56696
56697
56698 public function getCurrent()
56699 {
56700 if (empty($this->styles)) {
56701 return $this->emptyStyle;
56702 }
56703
56704 return $this->styles[\count($this->styles) - 1];
56705 }
56706
56707
56708
56709
56710 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
56711 {
56712 $this->emptyStyle = $emptyStyle;
56713
56714 return $this;
56715 }
56716
56717
56718
56719
56720 public function getEmptyStyle()
56721 {
56722 return $this->emptyStyle;
56723 }
56724 }
56725 <?php
56726
56727
56728
56729
56730
56731
56732
56733
56734
56735
56736 namespace Symfony\Component\Console\Helper;
56737
56738
56739
56740
56741
56742
56743
56744
56745 class DebugFormatterHelper extends Helper
56746 {
56747 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
56748 private $started = array();
56749 private $count = -1;
56750
56751
56752
56753
56754
56755
56756
56757
56758
56759
56760 public function start($id, $message, $prefix = 'RUN')
56761 {
56762 $this->started[$id] = array('border' => ++$this->count % \count($this->colors));
56763
56764 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
56765 }
56766
56767
56768
56769
56770
56771
56772
56773
56774
56775
56776
56777
56778 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
56779 {
56780 $message = '';
56781
56782 if ($error) {
56783 if (isset($this->started[$id]['out'])) {
56784 $message .= "\n";
56785 unset($this->started[$id]['out']);
56786 }
56787 if (!isset($this->started[$id]['err'])) {
56788 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
56789 $this->started[$id]['err'] = true;
56790 }
56791
56792 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
56793 } else {
56794 if (isset($this->started[$id]['err'])) {
56795 $message .= "\n";
56796 unset($this->started[$id]['err']);
56797 }
56798 if (!isset($this->started[$id]['out'])) {
56799 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
56800 $this->started[$id]['out'] = true;
56801 }
56802
56803 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
56804 }
56805
56806 return $message;
56807 }
56808
56809
56810
56811
56812
56813
56814
56815
56816
56817
56818
56819 public function stop($id, $message, $successful, $prefix = 'RES')
56820 {
56821 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
56822
56823 if ($successful) {
56824 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
56825 }
56826
56827 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
56828
56829 unset($this->started[$id]['out'], $this->started[$id]['err']);
56830
56831 return $message;
56832 }
56833
56834
56835
56836
56837
56838
56839 private function getBorder($id)
56840 {
56841 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
56842 }
56843
56844
56845
56846
56847 public function getName()
56848 {
56849 return 'debug_formatter';
56850 }
56851 }
56852 <?php
56853
56854
56855
56856
56857
56858
56859
56860
56861
56862
56863 namespace Symfony\Component\Console\Helper;
56864
56865 use Symfony\Component\Console\Descriptor\DescriptorInterface;
56866 use Symfony\Component\Console\Descriptor\JsonDescriptor;
56867 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
56868 use Symfony\Component\Console\Descriptor\TextDescriptor;
56869 use Symfony\Component\Console\Descriptor\XmlDescriptor;
56870 use Symfony\Component\Console\Exception\InvalidArgumentException;
56871 use Symfony\Component\Console\Output\OutputInterface;
56872
56873
56874
56875
56876
56877
56878 class DescriptorHelper extends Helper
56879 {
56880
56881
56882
56883 private $descriptors = array();
56884
56885 public function __construct()
56886 {
56887 $this
56888 ->register('txt', new TextDescriptor())
56889 ->register('xml', new XmlDescriptor())
56890 ->register('json', new JsonDescriptor())
56891 ->register('md', new MarkdownDescriptor())
56892 ;
56893 }
56894
56895
56896
56897
56898
56899
56900
56901
56902
56903
56904
56905
56906
56907
56908 public function describe(OutputInterface $output, $object, array $options = array())
56909 {
56910 $options = array_merge(array(
56911 'raw_text' => false,
56912 'format' => 'txt',
56913 ), $options);
56914
56915 if (!isset($this->descriptors[$options['format']])) {
56916 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
56917 }
56918
56919 $descriptor = $this->descriptors[$options['format']];
56920 $descriptor->describe($output, $object, $options);
56921 }
56922
56923
56924
56925
56926
56927
56928
56929
56930
56931 public function register($format, DescriptorInterface $descriptor)
56932 {
56933 $this->descriptors[$format] = $descriptor;
56934
56935 return $this;
56936 }
56937
56938
56939
56940
56941 public function getName()
56942 {
56943 return 'descriptor';
56944 }
56945 }
56946 <?php
56947
56948
56949
56950
56951
56952
56953
56954
56955
56956
56957 namespace Symfony\Component\Console\Helper;
56958
56959 use Symfony\Component\Console\Exception\InvalidArgumentException;
56960 use Symfony\Component\Console\Exception\RuntimeException;
56961 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
56962 use Symfony\Component\Console\Output\ConsoleOutputInterface;
56963 use Symfony\Component\Console\Output\OutputInterface;
56964
56965
56966
56967
56968
56969
56970
56971
56972
56973 class DialogHelper extends InputAwareHelper
56974 {
56975 private $inputStream;
56976 private static $shell;
56977 private static $stty;
56978
56979 public function __construct($triggerDeprecationError = true)
56980 {
56981 if ($triggerDeprecationError) {
56982 @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
56983 }
56984 }
56985
56986
56987
56988
56989
56990
56991
56992
56993
56994
56995
56996
56997
56998
56999
57000
57001 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
57002 {
57003 if ($output instanceof ConsoleOutputInterface) {
57004 $output = $output->getErrorOutput();
57005 }
57006
57007 $width = max(array_map('strlen', array_keys($choices)));
57008
57009 $messages = (array) $question;
57010 foreach ($choices as $key => $value) {
57011 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
57012 }
57013
57014 $output->writeln($messages);
57015
57016 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
57017
57018 $selectedChoices = str_replace(' ', '', $picked);
57019
57020 if ($multiselect) {
57021
57022 if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
57023 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
57024 }
57025 $selectedChoices = explode(',', $selectedChoices);
57026 } else {
57027 $selectedChoices = array($picked);
57028 }
57029
57030 $multiselectChoices = array();
57031
57032 foreach ($selectedChoices as $value) {
57033 if (empty($choices[$value])) {
57034 throw new InvalidArgumentException(sprintf($errorMessage, $value));
57035 }
57036 $multiselectChoices[] = $value;
57037 }
57038
57039 if ($multiselect) {
57040 return $multiselectChoices;
57041 }
57042
57043 return $picked;
57044 }, $attempts, $default);
57045
57046 return $result;
57047 }
57048
57049
57050
57051
57052
57053
57054
57055
57056
57057
57058
57059
57060
57061 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
57062 {
57063 if ($this->input && !$this->input->isInteractive()) {
57064 return $default;
57065 }
57066
57067 if ($output instanceof ConsoleOutputInterface) {
57068 $output = $output->getErrorOutput();
57069 }
57070
57071 $output->write($question);
57072
57073 $inputStream = $this->inputStream ?: STDIN;
57074
57075 if (null === $autocomplete || !$this->hasSttyAvailable()) {
57076 $ret = fgets($inputStream, 4096);
57077 if (false === $ret) {
57078 throw new RuntimeException('Aborted');
57079 }
57080 $ret = trim($ret);
57081 } else {
57082 $ret = '';
57083
57084 $i = 0;
57085 $ofs = -1;
57086 $matches = $autocomplete;
57087 $numMatches = \count($matches);
57088
57089 $sttyMode = shell_exec('stty -g');
57090
57091
57092 shell_exec('stty -icanon -echo');
57093
57094
57095 $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
57096
57097
57098 while (!feof($inputStream)) {
57099 $c = fread($inputStream, 1);
57100
57101
57102 if ("\177" === $c) {
57103 if (0 === $numMatches && 0 !== $i) {
57104 --$i;
57105
57106 $output->write("\033[1D");
57107 }
57108
57109 if (0 === $i) {
57110 $ofs = -1;
57111 $matches = $autocomplete;
57112 $numMatches = \count($matches);
57113 } else {
57114 $numMatches = 0;
57115 }
57116
57117
57118 $ret = substr($ret, 0, $i);
57119 } elseif ("\033" === $c) {
57120
57121 $c .= fread($inputStream, 2);
57122
57123
57124 if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
57125 if ('A' === $c[2] && -1 === $ofs) {
57126 $ofs = 0;
57127 }
57128
57129 if (0 === $numMatches) {
57130 continue;
57131 }
57132
57133 $ofs += ('A' === $c[2]) ? -1 : 1;
57134 $ofs = ($numMatches + $ofs) % $numMatches;
57135 }
57136 } elseif (\ord($c) < 32) {
57137 if ("\t" === $c || "\n" === $c) {
57138 if ($numMatches > 0 && -1 !== $ofs) {
57139 $ret = $matches[$ofs];
57140
57141 $output->write(substr($ret, $i));
57142 $i = \strlen($ret);
57143 }
57144
57145 if ("\n" === $c) {
57146 $output->write($c);
57147 break;
57148 }
57149
57150 $numMatches = 0;
57151 }
57152
57153 continue;
57154 } else {
57155 $output->write($c);
57156 $ret .= $c;
57157 ++$i;
57158
57159 $numMatches = 0;
57160 $ofs = 0;
57161
57162 foreach ($autocomplete as $value) {
57163
57164 if (0 === strpos($value, $ret) && $i !== \strlen($value)) {
57165 $matches[$numMatches++] = $value;
57166 }
57167 }
57168 }
57169
57170
57171 $output->write("\033[K");
57172
57173 if ($numMatches > 0 && -1 !== $ofs) {
57174
57175 $output->write("\0337");
57176
57177 $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
57178
57179 $output->write("\0338");
57180 }
57181 }
57182
57183
57184 shell_exec(sprintf('stty %s', $sttyMode));
57185 }
57186
57187 return \strlen($ret) > 0 ? $ret : $default;
57188 }
57189
57190
57191
57192
57193
57194
57195
57196
57197
57198
57199
57200
57201 public function askConfirmation(OutputInterface $output, $question, $default = true)
57202 {
57203 $answer = 'z';
57204 while ($answer && !\in_array(strtolower($answer[0]), array('y', 'n'))) {
57205 $answer = $this->ask($output, $question);
57206 }
57207
57208 if (false === $default) {
57209 return $answer && 'y' == strtolower($answer[0]);
57210 }
57211
57212 return !$answer || 'y' == strtolower($answer[0]);
57213 }
57214
57215
57216
57217
57218
57219
57220
57221
57222
57223
57224
57225
57226 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
57227 {
57228 if ($output instanceof ConsoleOutputInterface) {
57229 $output = $output->getErrorOutput();
57230 }
57231
57232 if ('\\' === \DIRECTORY_SEPARATOR) {
57233 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
57234
57235
57236 if ('phar:' === substr(__FILE__, 0, 5)) {
57237 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
57238 copy($exe, $tmpExe);
57239 $exe = $tmpExe;
57240 }
57241
57242 $output->write($question);
57243 $value = rtrim(shell_exec($exe));
57244 $output->writeln('');
57245
57246 if (isset($tmpExe)) {
57247 unlink($tmpExe);
57248 }
57249
57250 return $value;
57251 }
57252
57253 if ($this->hasSttyAvailable()) {
57254 $output->write($question);
57255
57256 $sttyMode = shell_exec('stty -g');
57257
57258 shell_exec('stty -echo');
57259 $value = fgets($this->inputStream ?: STDIN, 4096);
57260 shell_exec(sprintf('stty %s', $sttyMode));
57261
57262 if (false === $value) {
57263 throw new RuntimeException('Aborted');
57264 }
57265
57266 $value = trim($value);
57267 $output->writeln('');
57268
57269 return $value;
57270 }
57271
57272 if (false !== $shell = $this->getShell()) {
57273 $output->write($question);
57274 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
57275 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
57276 $value = rtrim(shell_exec($command));
57277 $output->writeln('');
57278
57279 return $value;
57280 }
57281
57282 if ($fallback) {
57283 return $this->ask($output, $question);
57284 }
57285
57286 throw new RuntimeException('Unable to hide the response');
57287 }
57288
57289
57290
57291
57292
57293
57294
57295
57296
57297
57298
57299
57300
57301
57302
57303
57304
57305
57306
57307 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
57308 {
57309 $that = $this;
57310
57311 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
57312 return $that->ask($output, $question, $default, $autocomplete);
57313 };
57314
57315 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
57316 }
57317
57318
57319
57320
57321
57322
57323
57324
57325
57326
57327
57328
57329
57330
57331
57332
57333
57334
57335
57336 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
57337 {
57338 $that = $this;
57339
57340 $interviewer = function () use ($output, $question, $fallback, $that) {
57341 return $that->askHiddenResponse($output, $question, $fallback);
57342 };
57343
57344 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
57345 }
57346
57347
57348
57349
57350
57351
57352
57353
57354 public function setInputStream($stream)
57355 {
57356 $this->inputStream = $stream;
57357 }
57358
57359
57360
57361
57362
57363
57364 public function getInputStream()
57365 {
57366 return $this->inputStream;
57367 }
57368
57369
57370
57371
57372 public function getName()
57373 {
57374 return 'dialog';
57375 }
57376
57377
57378
57379
57380
57381
57382 private function getShell()
57383 {
57384 if (null !== self::$shell) {
57385 return self::$shell;
57386 }
57387
57388 self::$shell = false;
57389
57390 if (file_exists('/usr/bin/env')) {
57391
57392 $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
57393 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
57394 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
57395 self::$shell = $sh;
57396 break;
57397 }
57398 }
57399 }
57400
57401 return self::$shell;
57402 }
57403
57404 private function hasSttyAvailable()
57405 {
57406 if (null !== self::$stty) {
57407 return self::$stty;
57408 }
57409
57410 exec('stty 2>&1', $output, $exitcode);
57411
57412 return self::$stty = 0 === $exitcode;
57413 }
57414
57415
57416
57417
57418
57419
57420
57421
57422
57423
57424
57425
57426
57427 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
57428 {
57429 if ($output instanceof ConsoleOutputInterface) {
57430 $output = $output->getErrorOutput();
57431 }
57432
57433 $e = null;
57434 while (false === $attempts || $attempts--) {
57435 if (null !== $e) {
57436 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
57437 }
57438
57439 try {
57440 return \call_user_func($validator, $interviewer());
57441 } catch (\Exception $e) {
57442 }
57443 }
57444
57445 throw $e;
57446 }
57447 }
57448 <?php
57449
57450
57451
57452
57453
57454
57455
57456
57457
57458
57459 namespace Symfony\Component\Console\Helper;
57460
57461 use Symfony\Component\Console\Formatter\OutputFormatter;
57462
57463
57464
57465
57466
57467
57468 class FormatterHelper extends Helper
57469 {
57470
57471
57472
57473
57474
57475
57476
57477
57478
57479 public function formatSection($section, $message, $style = 'info')
57480 {
57481 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
57482 }
57483
57484
57485
57486
57487
57488
57489
57490
57491
57492
57493 public function formatBlock($messages, $style, $large = false)
57494 {
57495 if (!\is_array($messages)) {
57496 $messages = array($messages);
57497 }
57498
57499 $len = 0;
57500 $lines = array();
57501 foreach ($messages as $message) {
57502 $message = OutputFormatter::escape($message);
57503 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
57504 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
57505 }
57506
57507 $messages = $large ? array(str_repeat(' ', $len)) : array();
57508 for ($i = 0; isset($lines[$i]); ++$i) {
57509 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
57510 }
57511 if ($large) {
57512 $messages[] = str_repeat(' ', $len);
57513 }
57514
57515 for ($i = 0; isset($messages[$i]); ++$i) {
57516 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
57517 }
57518
57519 return implode("\n", $messages);
57520 }
57521
57522
57523
57524
57525 public function getName()
57526 {
57527 return 'formatter';
57528 }
57529 }
57530 <?php
57531
57532
57533
57534
57535
57536
57537
57538
57539
57540
57541 namespace Symfony\Component\Console\Helper;
57542
57543 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
57544
57545
57546
57547
57548
57549
57550 abstract class Helper implements HelperInterface
57551 {
57552 protected $helperSet = null;
57553
57554
57555
57556
57557 public function setHelperSet(HelperSet $helperSet = null)
57558 {
57559 $this->helperSet = $helperSet;
57560 }
57561
57562
57563
57564
57565 public function getHelperSet()
57566 {
57567 return $this->helperSet;
57568 }
57569
57570
57571
57572
57573
57574
57575
57576
57577 public static function strlen($string)
57578 {
57579 if (false === $encoding = mb_detect_encoding($string, null, true)) {
57580 return \strlen($string);
57581 }
57582
57583 return mb_strwidth($string, $encoding);
57584 }
57585
57586 public static function formatTime($secs)
57587 {
57588 static $timeFormats = array(
57589 array(0, '< 1 sec'),
57590 array(1, '1 sec'),
57591 array(2, 'secs', 1),
57592 array(60, '1 min'),
57593 array(120, 'mins', 60),
57594 array(3600, '1 hr'),
57595 array(7200, 'hrs', 3600),
57596 array(86400, '1 day'),
57597 array(172800, 'days', 86400),
57598 );
57599
57600 foreach ($timeFormats as $index => $format) {
57601 if ($secs >= $format[0]) {
57602 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
57603 || $index == \count($timeFormats) - 1
57604 ) {
57605 if (2 == \count($format)) {
57606 return $format[1];
57607 }
57608
57609 return floor($secs / $format[2]).' '.$format[1];
57610 }
57611 }
57612 }
57613 }
57614
57615 public static function formatMemory($memory)
57616 {
57617 if ($memory >= 1024 * 1024 * 1024) {
57618 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
57619 }
57620
57621 if ($memory >= 1024 * 1024) {
57622 return sprintf('%.1f MiB', $memory / 1024 / 1024);
57623 }
57624
57625 if ($memory >= 1024) {
57626 return sprintf('%d KiB', $memory / 1024);
57627 }
57628
57629 return sprintf('%d B', $memory);
57630 }
57631
57632 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
57633 {
57634 return self::strlen(self::removeDecoration($formatter, $string));
57635 }
57636
57637 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
57638 {
57639 $isDecorated = $formatter->isDecorated();
57640 $formatter->setDecorated(false);
57641
57642 $string = $formatter->format($string);
57643
57644 $string = preg_replace("/\033\[[^m]*m/", '', $string);
57645 $formatter->setDecorated($isDecorated);
57646
57647 return $string;
57648 }
57649 }
57650 <?php
57651
57652
57653
57654
57655
57656
57657
57658
57659
57660
57661 namespace Symfony\Component\Console\Helper;
57662
57663
57664
57665
57666
57667
57668 interface HelperInterface
57669 {
57670
57671
57672
57673 public function setHelperSet(HelperSet $helperSet = null);
57674
57675
57676
57677
57678
57679
57680 public function getHelperSet();
57681
57682
57683
57684
57685
57686
57687 public function getName();
57688 }
57689 <?php
57690
57691
57692
57693
57694
57695
57696
57697
57698
57699
57700 namespace Symfony\Component\Console\Helper;
57701
57702 use Symfony\Component\Console\Command\Command;
57703 use Symfony\Component\Console\Exception\InvalidArgumentException;
57704
57705
57706
57707
57708
57709
57710 class HelperSet implements \IteratorAggregate
57711 {
57712
57713
57714
57715 private $helpers = array();
57716 private $command;
57717
57718
57719
57720
57721 public function __construct(array $helpers = array())
57722 {
57723 foreach ($helpers as $alias => $helper) {
57724 $this->set($helper, \is_int($alias) ? null : $alias);
57725 }
57726 }
57727
57728
57729
57730
57731
57732
57733
57734 public function set(HelperInterface $helper, $alias = null)
57735 {
57736 $this->helpers[$helper->getName()] = $helper;
57737 if (null !== $alias) {
57738 $this->helpers[$alias] = $helper;
57739 }
57740
57741 $helper->setHelperSet($this);
57742 }
57743
57744
57745
57746
57747
57748
57749
57750
57751 public function has($name)
57752 {
57753 return isset($this->helpers[$name]);
57754 }
57755
57756
57757
57758
57759
57760
57761
57762
57763
57764
57765 public function get($name)
57766 {
57767 if (!$this->has($name)) {
57768 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
57769 }
57770
57771 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
57772 @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
57773 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
57774 @trigger_error('"Symfony\Component\Console\Helper\ProgressHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\ProgressBar" instead.', E_USER_DEPRECATED);
57775 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
57776 @trigger_error('"Symfony\Component\Console\Helper\TableHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\Table" instead.', E_USER_DEPRECATED);
57777 }
57778
57779 return $this->helpers[$name];
57780 }
57781
57782 public function setCommand(Command $command = null)
57783 {
57784 $this->command = $command;
57785 }
57786
57787
57788
57789
57790
57791
57792 public function getCommand()
57793 {
57794 return $this->command;
57795 }
57796
57797
57798
57799
57800 public function getIterator()
57801 {
57802 return new \ArrayIterator($this->helpers);
57803 }
57804 }
57805 <?php
57806
57807
57808
57809
57810
57811
57812
57813
57814
57815
57816 namespace Symfony\Component\Console\Helper;
57817
57818 use Symfony\Component\Console\Input\InputAwareInterface;
57819 use Symfony\Component\Console\Input\InputInterface;
57820
57821
57822
57823
57824
57825
57826 abstract class InputAwareHelper extends Helper implements InputAwareInterface
57827 {
57828 protected $input;
57829
57830
57831
57832
57833 public function setInput(InputInterface $input)
57834 {
57835 $this->input = $input;
57836 }
57837 }
57838 <?php
57839
57840
57841
57842
57843
57844
57845
57846
57847
57848
57849 namespace Symfony\Component\Console\Helper;
57850
57851 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57852 use Symfony\Component\Console\Output\OutputInterface;
57853 use Symfony\Component\Process\Exception\ProcessFailedException;
57854 use Symfony\Component\Process\Process;
57855 use Symfony\Component\Process\ProcessBuilder;
57856
57857
57858
57859
57860
57861
57862 class ProcessHelper extends Helper
57863 {
57864
57865
57866
57867
57868
57869
57870
57871
57872
57873
57874
57875
57876 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
57877 {
57878 if ($output instanceof ConsoleOutputInterface) {
57879 $output = $output->getErrorOutput();
57880 }
57881
57882 $formatter = $this->getHelperSet()->get('debug_formatter');
57883
57884 if (\is_array($cmd)) {
57885 $process = ProcessBuilder::create($cmd)->getProcess();
57886 } elseif ($cmd instanceof Process) {
57887 $process = $cmd;
57888 } else {
57889 $process = new Process($cmd);
57890 }
57891
57892 if ($verbosity <= $output->getVerbosity()) {
57893 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
57894 }
57895
57896 if ($output->isDebug()) {
57897 $callback = $this->wrapCallback($output, $process, $callback);
57898 }
57899
57900 $process->run($callback);
57901
57902 if ($verbosity <= $output->getVerbosity()) {
57903 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
57904 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
57905 }
57906
57907 if (!$process->isSuccessful() && null !== $error) {
57908 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
57909 }
57910
57911 return $process;
57912 }
57913
57914
57915
57916
57917
57918
57919
57920
57921
57922
57923
57924
57925
57926
57927
57928
57929
57930
57931
57932 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
57933 {
57934 $process = $this->run($output, $cmd, $error, $callback);
57935
57936 if (!$process->isSuccessful()) {
57937 throw new ProcessFailedException($process);
57938 }
57939
57940 return $process;
57941 }
57942
57943
57944
57945
57946
57947
57948
57949
57950
57951
57952 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
57953 {
57954 if ($output instanceof ConsoleOutputInterface) {
57955 $output = $output->getErrorOutput();
57956 }
57957
57958 $formatter = $this->getHelperSet()->get('debug_formatter');
57959
57960 $that = $this;
57961
57962 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
57963 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
57964
57965 if (null !== $callback) {
57966 \call_user_func($callback, $type, $buffer);
57967 }
57968 };
57969 }
57970
57971
57972
57973
57974
57975
57976 public function escapeString($str)
57977 {
57978 return str_replace('<', '\\<', $str);
57979 }
57980
57981
57982
57983
57984 public function getName()
57985 {
57986 return 'process';
57987 }
57988 }
57989 <?php
57990
57991
57992
57993
57994
57995
57996
57997
57998
57999
58000 namespace Symfony\Component\Console\Helper;
58001
58002 use Symfony\Component\Console\Exception\LogicException;
58003 use Symfony\Component\Console\Output\ConsoleOutputInterface;
58004 use Symfony\Component\Console\Output\OutputInterface;
58005
58006
58007
58008
58009
58010
58011
58012 class ProgressBar
58013 {
58014 private $barWidth = 28;
58015 private $barChar;
58016 private $emptyBarChar = '-';
58017 private $progressChar = '>';
58018 private $format;
58019 private $internalFormat;
58020 private $redrawFreq = 1;
58021 private $output;
58022 private $step = 0;
58023 private $max;
58024 private $startTime;
58025 private $stepWidth;
58026 private $percent = 0.0;
58027 private $formatLineCount;
58028 private $messages = array();
58029 private $overwrite = true;
58030 private $firstRun = true;
58031
58032 private static $formatters;
58033 private static $formats;
58034
58035
58036
58037
58038
58039 public function __construct(OutputInterface $output, $max = 0)
58040 {
58041 if ($output instanceof ConsoleOutputInterface) {
58042 $output = $output->getErrorOutput();
58043 }
58044
58045 $this->output = $output;
58046 $this->setMaxSteps($max);
58047
58048 if (!$this->output->isDecorated()) {
58049
58050 $this->overwrite = false;
58051
58052
58053 $this->setRedrawFrequency($max / 10);
58054 }
58055
58056 $this->startTime = time();
58057 }
58058
58059
58060
58061
58062
58063
58064
58065
58066
58067 public static function setPlaceholderFormatterDefinition($name, $callable)
58068 {
58069 if (!self::$formatters) {
58070 self::$formatters = self::initPlaceholderFormatters();
58071 }
58072
58073 self::$formatters[$name] = $callable;
58074 }
58075
58076
58077
58078
58079
58080
58081
58082
58083 public static function getPlaceholderFormatterDefinition($name)
58084 {
58085 if (!self::$formatters) {
58086 self::$formatters = self::initPlaceholderFormatters();
58087 }
58088
58089 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
58090 }
58091
58092
58093
58094
58095
58096
58097
58098
58099
58100 public static function setFormatDefinition($name, $format)
58101 {
58102 if (!self::$formats) {
58103 self::$formats = self::initFormats();
58104 }
58105
58106 self::$formats[$name] = $format;
58107 }
58108
58109
58110
58111
58112
58113
58114
58115
58116 public static function getFormatDefinition($name)
58117 {
58118 if (!self::$formats) {
58119 self::$formats = self::initFormats();
58120 }
58121
58122 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
58123 }
58124
58125
58126
58127
58128
58129
58130
58131
58132
58133
58134
58135 public function setMessage($message, $name = 'message')
58136 {
58137 $this->messages[$name] = $message;
58138 }
58139
58140 public function getMessage($name = 'message')
58141 {
58142 return $this->messages[$name];
58143 }
58144
58145
58146
58147
58148
58149
58150 public function getStartTime()
58151 {
58152 return $this->startTime;
58153 }
58154
58155
58156
58157
58158
58159
58160 public function getMaxSteps()
58161 {
58162 return $this->max;
58163 }
58164
58165
58166
58167
58168
58169
58170
58171
58172 public function getStep()
58173 {
58174 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the getProgress() method instead.', E_USER_DEPRECATED);
58175
58176 return $this->getProgress();
58177 }
58178
58179
58180
58181
58182
58183
58184 public function getProgress()
58185 {
58186 return $this->step;
58187 }
58188
58189
58190
58191
58192
58193
58194
58195
58196 public function getStepWidth()
58197 {
58198 return $this->stepWidth;
58199 }
58200
58201
58202
58203
58204
58205
58206 public function getProgressPercent()
58207 {
58208 return $this->percent;
58209 }
58210
58211
58212
58213
58214
58215
58216 public function setBarWidth($size)
58217 {
58218 $this->barWidth = (int) $size;
58219 }
58220
58221
58222
58223
58224
58225
58226 public function getBarWidth()
58227 {
58228 return $this->barWidth;
58229 }
58230
58231
58232
58233
58234
58235
58236 public function setBarCharacter($char)
58237 {
58238 $this->barChar = $char;
58239 }
58240
58241
58242
58243
58244
58245
58246 public function getBarCharacter()
58247 {
58248 if (null === $this->barChar) {
58249 return $this->max ? '=' : $this->emptyBarChar;
58250 }
58251
58252 return $this->barChar;
58253 }
58254
58255
58256
58257
58258
58259
58260 public function setEmptyBarCharacter($char)
58261 {
58262 $this->emptyBarChar = $char;
58263 }
58264
58265
58266
58267
58268
58269
58270 public function getEmptyBarCharacter()
58271 {
58272 return $this->emptyBarChar;
58273 }
58274
58275
58276
58277
58278
58279
58280 public function setProgressCharacter($char)
58281 {
58282 $this->progressChar = $char;
58283 }
58284
58285
58286
58287
58288
58289
58290 public function getProgressCharacter()
58291 {
58292 return $this->progressChar;
58293 }
58294
58295
58296
58297
58298
58299
58300 public function setFormat($format)
58301 {
58302 $this->format = null;
58303 $this->internalFormat = $format;
58304 }
58305
58306
58307
58308
58309
58310
58311 public function setRedrawFrequency($freq)
58312 {
58313 $this->redrawFreq = max((int) $freq, 1);
58314 }
58315
58316
58317
58318
58319
58320
58321 public function start($max = null)
58322 {
58323 $this->startTime = time();
58324 $this->step = 0;
58325 $this->percent = 0.0;
58326
58327 if (null !== $max) {
58328 $this->setMaxSteps($max);
58329 }
58330
58331 $this->display();
58332 }
58333
58334
58335
58336
58337
58338
58339
58340
58341 public function advance($step = 1)
58342 {
58343 $this->setProgress($this->step + $step);
58344 }
58345
58346
58347
58348
58349
58350
58351
58352
58353
58354
58355 public function setCurrent($step)
58356 {
58357 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the setProgress() method instead.', E_USER_DEPRECATED);
58358
58359 $this->setProgress($step);
58360 }
58361
58362
58363
58364
58365
58366
58367 public function setOverwrite($overwrite)
58368 {
58369 $this->overwrite = (bool) $overwrite;
58370 }
58371
58372
58373
58374
58375
58376
58377
58378
58379 public function setProgress($step)
58380 {
58381 $step = (int) $step;
58382 if ($step < $this->step) {
58383 throw new LogicException('You can\'t regress the progress bar.');
58384 }
58385
58386 if ($this->max && $step > $this->max) {
58387 $this->max = $step;
58388 }
58389
58390 $prevPeriod = (int) ($this->step / $this->redrawFreq);
58391 $currPeriod = (int) ($step / $this->redrawFreq);
58392 $this->step = $step;
58393 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
58394 if ($prevPeriod !== $currPeriod || $this->max === $step) {
58395 $this->display();
58396 }
58397 }
58398
58399
58400
58401
58402 public function finish()
58403 {
58404 if (!$this->max) {
58405 $this->max = $this->step;
58406 }
58407
58408 if ($this->step === $this->max && !$this->overwrite) {
58409
58410 return;
58411 }
58412
58413 $this->setProgress($this->max);
58414 }
58415
58416
58417
58418
58419 public function display()
58420 {
58421 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
58422 return;
58423 }
58424
58425 if (null === $this->format) {
58426 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
58427 }
58428
58429
58430 $self = $this;
58431 $output = $this->output;
58432 $messages = $this->messages;
58433 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
58434 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
58435 $text = \call_user_func($formatter, $self, $output);
58436 } elseif (isset($messages[$matches[1]])) {
58437 $text = $messages[$matches[1]];
58438 } else {
58439 return $matches[0];
58440 }
58441
58442 if (isset($matches[2])) {
58443 $text = sprintf('%'.$matches[2], $text);
58444 }
58445
58446 return $text;
58447 }, $this->format));
58448 }
58449
58450
58451
58452
58453
58454
58455
58456
58457 public function clear()
58458 {
58459 if (!$this->overwrite) {
58460 return;
58461 }
58462
58463 if (null === $this->format) {
58464 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
58465 }
58466
58467 $this->overwrite('');
58468 }
58469
58470
58471
58472
58473
58474
58475 private function setRealFormat($format)
58476 {
58477
58478 if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
58479 $this->format = self::getFormatDefinition($format.'_nomax');
58480 } elseif (null !== self::getFormatDefinition($format)) {
58481 $this->format = self::getFormatDefinition($format);
58482 } else {
58483 $this->format = $format;
58484 }
58485
58486 $this->formatLineCount = substr_count($this->format, "\n");
58487 }
58488
58489
58490
58491
58492
58493
58494 private function setMaxSteps($max)
58495 {
58496 $this->max = max(0, (int) $max);
58497 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
58498 }
58499
58500
58501
58502
58503
58504
58505 private function overwrite($message)
58506 {
58507 if ($this->overwrite) {
58508 if (!$this->firstRun) {
58509
58510 $this->output->write("\x0D");
58511
58512
58513 $this->output->write("\x1B[2K");
58514
58515
58516 if ($this->formatLineCount > 0) {
58517 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
58518 }
58519 }
58520 } elseif ($this->step > 0) {
58521 $this->output->writeln('');
58522 }
58523
58524 $this->firstRun = false;
58525
58526 $this->output->write($message);
58527 }
58528
58529 private function determineBestFormat()
58530 {
58531 switch ($this->output->getVerbosity()) {
58532
58533 case OutputInterface::VERBOSITY_VERBOSE:
58534 return $this->max ? 'verbose' : 'verbose_nomax';
58535 case OutputInterface::VERBOSITY_VERY_VERBOSE:
58536 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
58537 case OutputInterface::VERBOSITY_DEBUG:
58538 return $this->max ? 'debug' : 'debug_nomax';
58539 default:
58540 return $this->max ? 'normal' : 'normal_nomax';
58541 }
58542 }
58543
58544 private static function initPlaceholderFormatters()
58545 {
58546 return array(
58547 'bar' => function (ProgressBar $bar, OutputInterface $output) {
58548 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
58549 $display = str_repeat($bar->getBarCharacter(), $completeBars);
58550 if ($completeBars < $bar->getBarWidth()) {
58551 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
58552 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
58553 }
58554
58555 return $display;
58556 },
58557 'elapsed' => function (ProgressBar $bar) {
58558 return Helper::formatTime(time() - $bar->getStartTime());
58559 },
58560 'remaining' => function (ProgressBar $bar) {
58561 if (!$bar->getMaxSteps()) {
58562 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
58563 }
58564
58565 if (!$bar->getProgress()) {
58566 $remaining = 0;
58567 } else {
58568 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
58569 }
58570
58571 return Helper::formatTime($remaining);
58572 },
58573 'estimated' => function (ProgressBar $bar) {
58574 if (!$bar->getMaxSteps()) {
58575 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
58576 }
58577
58578 if (!$bar->getProgress()) {
58579 $estimated = 0;
58580 } else {
58581 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
58582 }
58583
58584 return Helper::formatTime($estimated);
58585 },
58586 'memory' => function (ProgressBar $bar) {
58587 return Helper::formatMemory(memory_get_usage(true));
58588 },
58589 'current' => function (ProgressBar $bar) {
58590 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
58591 },
58592 'max' => function (ProgressBar $bar) {
58593 return $bar->getMaxSteps();
58594 },
58595 'percent' => function (ProgressBar $bar) {
58596 return floor($bar->getProgressPercent() * 100);
58597 },
58598 );
58599 }
58600
58601 private static function initFormats()
58602 {
58603 return array(
58604 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
58605 'normal_nomax' => ' %current% [%bar%]',
58606
58607 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
58608 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
58609
58610 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
58611 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
58612
58613 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
58614 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
58615 );
58616 }
58617 }
58618 <?php
58619
58620
58621
58622
58623
58624
58625
58626
58627
58628
58629 namespace Symfony\Component\Console\Helper;
58630
58631 use Symfony\Component\Console\Exception\LogicException;
58632 use Symfony\Component\Console\Output\ConsoleOutputInterface;
58633 use Symfony\Component\Console\Output\NullOutput;
58634 use Symfony\Component\Console\Output\OutputInterface;
58635
58636
58637
58638
58639
58640
58641
58642
58643
58644
58645 class ProgressHelper extends Helper
58646 {
58647 const FORMAT_QUIET = ' %percent%%';
58648 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
58649 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
58650 const FORMAT_QUIET_NOMAX = ' %current%';
58651 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
58652 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
58653
58654
58655 private $barWidth = 28;
58656 private $barChar = '=';
58657 private $emptyBarChar = '-';
58658 private $progressChar = '>';
58659 private $format = null;
58660 private $redrawFreq = 1;
58661
58662 private $lastMessagesLength;
58663 private $barCharOriginal;
58664
58665
58666
58667
58668 private $output;
58669
58670
58671
58672
58673
58674
58675 private $current;
58676
58677
58678
58679
58680
58681
58682 private $max;
58683
58684
58685
58686
58687
58688
58689 private $startTime;
58690
58691
58692
58693
58694
58695
58696 private $defaultFormatVars = array(
58697 'current',
58698 'max',
58699 'bar',
58700 'percent',
58701 'elapsed',
58702 );
58703
58704
58705
58706
58707
58708
58709 private $formatVars;
58710
58711
58712
58713
58714
58715
58716 private $widths = array(
58717 'current' => 4,
58718 'max' => 4,
58719 'percent' => 3,
58720 'elapsed' => 6,
58721 );
58722
58723
58724
58725
58726
58727
58728 private $timeFormats = array(
58729 array(0, '???'),
58730 array(2, '1 sec'),
58731 array(59, 'secs', 1),
58732 array(60, '1 min'),
58733 array(3600, 'mins', 60),
58734 array(5400, '1 hr'),
58735 array(86400, 'hrs', 3600),
58736 array(129600, '1 day'),
58737 array(604800, 'days', 86400),
58738 );
58739
58740 public function __construct($triggerDeprecationError = true)
58741 {
58742 if ($triggerDeprecationError) {
58743 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\ProgressBar class instead.', E_USER_DEPRECATED);
58744 }
58745 }
58746
58747
58748
58749
58750
58751
58752 public function setBarWidth($size)
58753 {
58754 $this->barWidth = (int) $size;
58755 }
58756
58757
58758
58759
58760
58761
58762 public function setBarCharacter($char)
58763 {
58764 $this->barChar = $char;
58765 }
58766
58767
58768
58769
58770
58771
58772 public function setEmptyBarCharacter($char)
58773 {
58774 $this->emptyBarChar = $char;
58775 }
58776
58777
58778
58779
58780
58781
58782 public function setProgressCharacter($char)
58783 {
58784 $this->progressChar = $char;
58785 }
58786
58787
58788
58789
58790
58791
58792 public function setFormat($format)
58793 {
58794 $this->format = $format;
58795 }
58796
58797
58798
58799
58800
58801
58802 public function setRedrawFrequency($freq)
58803 {
58804 $this->redrawFreq = (int) $freq;
58805 }
58806
58807
58808
58809
58810
58811
58812
58813 public function start(OutputInterface $output, $max = null)
58814 {
58815 if ($output instanceof ConsoleOutputInterface) {
58816 $output = $output->getErrorOutput();
58817 }
58818
58819 $this->startTime = time();
58820 $this->current = 0;
58821 $this->max = (int) $max;
58822
58823
58824 $this->output = $output->isDecorated() ? $output : new NullOutput();
58825 $this->lastMessagesLength = 0;
58826 $this->barCharOriginal = '';
58827
58828 if (null === $this->format) {
58829 switch ($output->getVerbosity()) {
58830 case OutputInterface::VERBOSITY_QUIET:
58831 $this->format = self::FORMAT_QUIET_NOMAX;
58832 if ($this->max > 0) {
58833 $this->format = self::FORMAT_QUIET;
58834 }
58835 break;
58836 case OutputInterface::VERBOSITY_VERBOSE:
58837 case OutputInterface::VERBOSITY_VERY_VERBOSE:
58838 case OutputInterface::VERBOSITY_DEBUG:
58839 $this->format = self::FORMAT_VERBOSE_NOMAX;
58840 if ($this->max > 0) {
58841 $this->format = self::FORMAT_VERBOSE;
58842 }
58843 break;
58844 default:
58845 $this->format = self::FORMAT_NORMAL_NOMAX;
58846 if ($this->max > 0) {
58847 $this->format = self::FORMAT_NORMAL;
58848 }
58849 break;
58850 }
58851 }
58852
58853 $this->initialize();
58854 }
58855
58856
58857
58858
58859
58860
58861
58862
58863
58864 public function advance($step = 1, $redraw = false)
58865 {
58866 $this->setCurrent($this->current + $step, $redraw);
58867 }
58868
58869
58870
58871
58872
58873
58874
58875
58876
58877 public function setCurrent($current, $redraw = false)
58878 {
58879 if (null === $this->startTime) {
58880 throw new LogicException('You must start the progress bar before calling setCurrent().');
58881 }
58882
58883 $current = (int) $current;
58884
58885 if ($current < $this->current) {
58886 throw new LogicException('You can\'t regress the progress bar');
58887 }
58888
58889 if (0 === $this->current) {
58890 $redraw = true;
58891 }
58892
58893 $prevPeriod = (int) ($this->current / $this->redrawFreq);
58894
58895 $this->current = $current;
58896
58897 $currPeriod = (int) ($this->current / $this->redrawFreq);
58898 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
58899 $this->display();
58900 }
58901 }
58902
58903
58904
58905
58906
58907
58908
58909
58910 public function display($finish = false)
58911 {
58912 if (null === $this->startTime) {
58913 throw new LogicException('You must start the progress bar before calling display().');
58914 }
58915
58916 $message = $this->format;
58917 foreach ($this->generate($finish) as $name => $value) {
58918 $message = str_replace("%{$name}%", $value, $message);
58919 }
58920 $this->overwrite($this->output, $message);
58921 }
58922
58923
58924
58925
58926
58927
58928
58929
58930 public function clear()
58931 {
58932 $this->overwrite($this->output, '');
58933 }
58934
58935
58936
58937
58938 public function finish()
58939 {
58940 if (null === $this->startTime) {
58941 throw new LogicException('You must start the progress bar before calling finish().');
58942 }
58943
58944 if (null !== $this->startTime) {
58945 if (!$this->max) {
58946 $this->barChar = $this->barCharOriginal;
58947 $this->display(true);
58948 }
58949 $this->startTime = null;
58950 $this->output->writeln('');
58951 $this->output = null;
58952 }
58953 }
58954
58955
58956
58957
58958 private function initialize()
58959 {
58960 $this->formatVars = array();
58961 foreach ($this->defaultFormatVars as $var) {
58962 if (false !== strpos($this->format, "%{$var}%")) {
58963 $this->formatVars[$var] = true;
58964 }
58965 }
58966
58967 if ($this->max > 0) {
58968 $this->widths['max'] = $this->strlen($this->max);
58969 $this->widths['current'] = $this->widths['max'];
58970 } else {
58971 $this->barCharOriginal = $this->barChar;
58972 $this->barChar = $this->emptyBarChar;
58973 }
58974 }
58975
58976
58977
58978
58979
58980
58981
58982
58983 private function generate($finish = false)
58984 {
58985 $vars = array();
58986 $percent = 0;
58987 if ($this->max > 0) {
58988 $percent = (float) $this->current / $this->max;
58989 }
58990
58991 if (isset($this->formatVars['bar'])) {
58992 if ($this->max > 0) {
58993 $completeBars = floor($percent * $this->barWidth);
58994 } else {
58995 if (!$finish) {
58996 $completeBars = floor($this->current % $this->barWidth);
58997 } else {
58998 $completeBars = $this->barWidth;
58999 }
59000 }
59001
59002 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
59003 $bar = str_repeat($this->barChar, $completeBars);
59004 if ($completeBars < $this->barWidth) {
59005 $bar .= $this->progressChar;
59006 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
59007 }
59008
59009 $vars['bar'] = $bar;
59010 }
59011
59012 if (isset($this->formatVars['elapsed'])) {
59013 $elapsed = time() - $this->startTime;
59014 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
59015 }
59016
59017 if (isset($this->formatVars['current'])) {
59018 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
59019 }
59020
59021 if (isset($this->formatVars['max'])) {
59022 $vars['max'] = $this->max;
59023 }
59024
59025 if (isset($this->formatVars['percent'])) {
59026 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
59027 }
59028
59029 return $vars;
59030 }
59031
59032
59033
59034
59035
59036
59037
59038
59039 private function humaneTime($secs)
59040 {
59041 $text = '';
59042 foreach ($this->timeFormats as $format) {
59043 if ($secs < $format[0]) {
59044 if (2 == \count($format)) {
59045 $text = $format[1];
59046 break;
59047 } else {
59048 $text = ceil($secs / $format[2]).' '.$format[1];
59049 break;
59050 }
59051 }
59052 }
59053
59054 return $text;
59055 }
59056
59057
59058
59059
59060
59061
59062
59063 private function overwrite(OutputInterface $output, $message)
59064 {
59065 $length = $this->strlen($message);
59066
59067
59068 if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
59069 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
59070 }
59071
59072
59073 $output->write("\x0D");
59074 $output->write($message);
59075
59076 $this->lastMessagesLength = $this->strlen($message);
59077 }
59078
59079
59080
59081
59082 public function getName()
59083 {
59084 return 'progress';
59085 }
59086 }
59087 <?php
59088
59089
59090
59091
59092
59093
59094
59095
59096
59097
59098 namespace Symfony\Component\Console\Helper;
59099
59100 use Symfony\Component\Console\Exception\InvalidArgumentException;
59101 use Symfony\Component\Console\Exception\LogicException;
59102 use Symfony\Component\Console\Output\OutputInterface;
59103
59104
59105
59106
59107 class ProgressIndicator
59108 {
59109 private $output;
59110 private $startTime;
59111 private $format;
59112 private $message;
59113 private $indicatorValues;
59114 private $indicatorCurrent;
59115 private $indicatorChangeInterval;
59116 private $indicatorUpdateTime;
59117 private $started = false;
59118
59119 private static $formatters;
59120 private static $formats;
59121
59122
59123
59124
59125
59126
59127
59128 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
59129 {
59130 $this->output = $output;
59131
59132 if (null === $format) {
59133 $format = $this->determineBestFormat();
59134 }
59135
59136 if (null === $indicatorValues) {
59137 $indicatorValues = array('-', '\\', '|', '/');
59138 }
59139
59140 $indicatorValues = array_values($indicatorValues);
59141
59142 if (2 > \count($indicatorValues)) {
59143 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
59144 }
59145
59146 $this->format = self::getFormatDefinition($format);
59147 $this->indicatorChangeInterval = $indicatorChangeInterval;
59148 $this->indicatorValues = $indicatorValues;
59149 $this->startTime = time();
59150 }
59151
59152
59153
59154
59155
59156
59157 public function setMessage($message)
59158 {
59159 $this->message = $message;
59160
59161 $this->display();
59162 }
59163
59164
59165
59166
59167
59168
59169
59170
59171 public function getMessage()
59172 {
59173 return $this->message;
59174 }
59175
59176
59177
59178
59179
59180
59181
59182
59183 public function getStartTime()
59184 {
59185 return $this->startTime;
59186 }
59187
59188
59189
59190
59191
59192
59193
59194
59195 public function getCurrentValue()
59196 {
59197 return $this->indicatorValues[$this->indicatorCurrent % \count($this->indicatorValues)];
59198 }
59199
59200
59201
59202
59203
59204
59205 public function start($message)
59206 {
59207 if ($this->started) {
59208 throw new LogicException('Progress indicator already started.');
59209 }
59210
59211 $this->message = $message;
59212 $this->started = true;
59213 $this->startTime = time();
59214 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
59215 $this->indicatorCurrent = 0;
59216
59217 $this->display();
59218 }
59219
59220
59221
59222
59223 public function advance()
59224 {
59225 if (!$this->started) {
59226 throw new LogicException('Progress indicator has not yet been started.');
59227 }
59228
59229 if (!$this->output->isDecorated()) {
59230 return;
59231 }
59232
59233 $currentTime = $this->getCurrentTimeInMilliseconds();
59234
59235 if ($currentTime < $this->indicatorUpdateTime) {
59236 return;
59237 }
59238
59239 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
59240 ++$this->indicatorCurrent;
59241
59242 $this->display();
59243 }
59244
59245
59246
59247
59248
59249
59250 public function finish($message)
59251 {
59252 if (!$this->started) {
59253 throw new LogicException('Progress indicator has not yet been started.');
59254 }
59255
59256 $this->message = $message;
59257 $this->display();
59258 $this->output->writeln('');
59259 $this->started = false;
59260 }
59261
59262
59263
59264
59265
59266
59267
59268
59269 public static function getFormatDefinition($name)
59270 {
59271 if (!self::$formats) {
59272 self::$formats = self::initFormats();
59273 }
59274
59275 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
59276 }
59277
59278
59279
59280
59281
59282
59283
59284
59285
59286 public static function setPlaceholderFormatterDefinition($name, $callable)
59287 {
59288 if (!self::$formatters) {
59289 self::$formatters = self::initPlaceholderFormatters();
59290 }
59291
59292 self::$formatters[$name] = $callable;
59293 }
59294
59295
59296
59297
59298
59299
59300
59301
59302 public static function getPlaceholderFormatterDefinition($name)
59303 {
59304 if (!self::$formatters) {
59305 self::$formatters = self::initPlaceholderFormatters();
59306 }
59307
59308 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
59309 }
59310
59311 private function display()
59312 {
59313 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
59314 return;
59315 }
59316
59317 $self = $this;
59318
59319 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
59320 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
59321 return \call_user_func($formatter, $self);
59322 }
59323
59324 return $matches[0];
59325 }, $this->format));
59326 }
59327
59328 private function determineBestFormat()
59329 {
59330 switch ($this->output->getVerbosity()) {
59331
59332 case OutputInterface::VERBOSITY_VERBOSE:
59333 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
59334 case OutputInterface::VERBOSITY_VERY_VERBOSE:
59335 case OutputInterface::VERBOSITY_DEBUG:
59336 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
59337 default:
59338 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
59339 }
59340 }
59341
59342
59343
59344
59345
59346
59347 private function overwrite($message)
59348 {
59349 if ($this->output->isDecorated()) {
59350 $this->output->write("\x0D\x1B[2K");
59351 $this->output->write($message);
59352 } else {
59353 $this->output->writeln($message);
59354 }
59355 }
59356
59357 private function getCurrentTimeInMilliseconds()
59358 {
59359 return round(microtime(true) * 1000);
59360 }
59361
59362 private static function initPlaceholderFormatters()
59363 {
59364 return array(
59365 'indicator' => function (ProgressIndicator $indicator) {
59366 return $indicator->getCurrentValue();
59367 },
59368 'message' => function (ProgressIndicator $indicator) {
59369 return $indicator->getMessage();
59370 },
59371 'elapsed' => function (ProgressIndicator $indicator) {
59372 return Helper::formatTime(time() - $indicator->getStartTime());
59373 },
59374 'memory' => function () {
59375 return Helper::formatMemory(memory_get_usage(true));
59376 },
59377 );
59378 }
59379
59380 private static function initFormats()
59381 {
59382 return array(
59383 'normal' => ' %indicator% %message%',
59384 'normal_no_ansi' => ' %message%',
59385
59386 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
59387 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
59388
59389 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
59390 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
59391 );
59392 }
59393 }
59394 <?php
59395
59396
59397
59398
59399
59400
59401
59402
59403
59404
59405 namespace Symfony\Component\Console\Helper;
59406
59407 use Symfony\Component\Console\Exception\InvalidArgumentException;
59408 use Symfony\Component\Console\Exception\RuntimeException;
59409 use Symfony\Component\Console\Formatter\OutputFormatter;
59410 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
59411 use Symfony\Component\Console\Input\InputInterface;
59412 use Symfony\Component\Console\Output\ConsoleOutputInterface;
59413 use Symfony\Component\Console\Output\OutputInterface;
59414 use Symfony\Component\Console\Question\ChoiceQuestion;
59415 use Symfony\Component\Console\Question\Question;
59416
59417
59418
59419
59420
59421
59422 class QuestionHelper extends Helper
59423 {
59424 private $inputStream;
59425 private static $shell;
59426 private static $stty;
59427
59428
59429
59430
59431
59432
59433
59434
59435 public function ask(InputInterface $input, OutputInterface $output, Question $question)
59436 {
59437 if ($output instanceof ConsoleOutputInterface) {
59438 $output = $output->getErrorOutput();
59439 }
59440
59441 if (!$input->isInteractive()) {
59442 $default = $question->getDefault();
59443
59444 if (null !== $default && $question instanceof ChoiceQuestion) {
59445 $choices = $question->getChoices();
59446
59447 if (!$question->isMultiselect()) {
59448 return isset($choices[$default]) ? $choices[$default] : $default;
59449 }
59450
59451 $default = explode(',', $default);
59452 foreach ($default as $k => $v) {
59453 $v = trim($v);
59454 $default[$k] = isset($choices[$v]) ? $choices[$v] : $v;
59455 }
59456 }
59457
59458 return $default;
59459 }
59460
59461 if (!$question->getValidator()) {
59462 return $this->doAsk($output, $question);
59463 }
59464
59465 $that = $this;
59466
59467 $interviewer = function () use ($output, $question, $that) {
59468 return $that->doAsk($output, $question);
59469 };
59470
59471 return $this->validateAttempts($interviewer, $output, $question);
59472 }
59473
59474
59475
59476
59477
59478
59479
59480
59481
59482
59483 public function setInputStream($stream)
59484 {
59485 if (!\is_resource($stream)) {
59486 throw new InvalidArgumentException('Input stream must be a valid resource.');
59487 }
59488
59489 $this->inputStream = $stream;
59490 }
59491
59492
59493
59494
59495
59496
59497 public function getInputStream()
59498 {
59499 return $this->inputStream;
59500 }
59501
59502
59503
59504
59505 public function getName()
59506 {
59507 return 'question';
59508 }
59509
59510
59511
59512
59513
59514
59515
59516
59517
59518
59519 public function doAsk(OutputInterface $output, Question $question)
59520 {
59521 $this->writePrompt($output, $question);
59522
59523 $inputStream = $this->inputStream ?: STDIN;
59524 $autocomplete = $question->getAutocompleterValues();
59525
59526 if (null === $autocomplete || !$this->hasSttyAvailable()) {
59527 $ret = false;
59528 if ($question->isHidden()) {
59529 try {
59530 $ret = trim($this->getHiddenResponse($output, $inputStream));
59531 } catch (RuntimeException $e) {
59532 if (!$question->isHiddenFallback()) {
59533 throw $e;
59534 }
59535 }
59536 }
59537
59538 if (false === $ret) {
59539 $ret = fgets($inputStream, 4096);
59540 if (false === $ret) {
59541 throw new RuntimeException('Aborted');
59542 }
59543 $ret = trim($ret);
59544 }
59545 } else {
59546 $ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
59547 }
59548
59549 $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
59550
59551 if ($normalizer = $question->getNormalizer()) {
59552 return $normalizer($ret);
59553 }
59554
59555 return $ret;
59556 }
59557
59558
59559
59560
59561 protected function writePrompt(OutputInterface $output, Question $question)
59562 {
59563 $message = $question->getQuestion();
59564
59565 if ($question instanceof ChoiceQuestion) {
59566 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
59567
59568 $messages = (array) $question->getQuestion();
59569 foreach ($question->getChoices() as $key => $value) {
59570 $width = $maxWidth - $this->strlen($key);
59571 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
59572 }
59573
59574 $output->writeln($messages);
59575
59576 $message = $question->getPrompt();
59577 }
59578
59579 $output->write($message);
59580 }
59581
59582
59583
59584
59585 protected function writeError(OutputInterface $output, \Exception $error)
59586 {
59587 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
59588 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
59589 } else {
59590 $message = '<error>'.$error->getMessage().'</error>';
59591 }
59592
59593 $output->writeln($message);
59594 }
59595
59596
59597
59598
59599
59600
59601
59602
59603
59604
59605
59606 private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
59607 {
59608 $ret = '';
59609
59610 $i = 0;
59611 $ofs = -1;
59612 $matches = $autocomplete;
59613 $numMatches = \count($matches);
59614
59615 $sttyMode = shell_exec('stty -g');
59616
59617
59618 shell_exec('stty -icanon -echo');
59619
59620
59621 $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
59622
59623
59624 while (!feof($inputStream)) {
59625 $c = fread($inputStream, 1);
59626
59627
59628 if ("\177" === $c) {
59629 if (0 === $numMatches && 0 !== $i) {
59630 --$i;
59631
59632 $output->write("\033[1D");
59633 }
59634
59635 if (0 === $i) {
59636 $ofs = -1;
59637 $matches = $autocomplete;
59638 $numMatches = \count($matches);
59639 } else {
59640 $numMatches = 0;
59641 }
59642
59643
59644 $ret = substr($ret, 0, $i);
59645 } elseif ("\033" === $c) {
59646
59647 $c .= fread($inputStream, 2);
59648
59649
59650 if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
59651 if ('A' === $c[2] && -1 === $ofs) {
59652 $ofs = 0;
59653 }
59654
59655 if (0 === $numMatches) {
59656 continue;
59657 }
59658
59659 $ofs += ('A' === $c[2]) ? -1 : 1;
59660 $ofs = ($numMatches + $ofs) % $numMatches;
59661 }
59662 } elseif (\ord($c) < 32) {
59663 if ("\t" === $c || "\n" === $c) {
59664 if ($numMatches > 0 && -1 !== $ofs) {
59665 $ret = $matches[$ofs];
59666
59667 $output->write(substr($ret, $i));
59668 $i = \strlen($ret);
59669 }
59670
59671 if ("\n" === $c) {
59672 $output->write($c);
59673 break;
59674 }
59675
59676 $numMatches = 0;
59677 }
59678
59679 continue;
59680 } else {
59681 $output->write($c);
59682 $ret .= $c;
59683 ++$i;
59684
59685 $numMatches = 0;
59686 $ofs = 0;
59687
59688 foreach ($autocomplete as $value) {
59689
59690 if (0 === strpos($value, $ret)) {
59691 $matches[$numMatches++] = $value;
59692 }
59693 }
59694 }
59695
59696
59697 $output->write("\033[K");
59698
59699 if ($numMatches > 0 && -1 !== $ofs) {
59700
59701 $output->write("\0337");
59702
59703 $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
59704
59705 $output->write("\0338");
59706 }
59707 }
59708
59709
59710 shell_exec(sprintf('stty %s', $sttyMode));
59711
59712 return $ret;
59713 }
59714
59715
59716
59717
59718
59719
59720
59721
59722
59723
59724
59725 private function getHiddenResponse(OutputInterface $output, $inputStream)
59726 {
59727 if ('\\' === \DIRECTORY_SEPARATOR) {
59728 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
59729
59730
59731 if ('phar:' === substr(__FILE__, 0, 5)) {
59732 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
59733 copy($exe, $tmpExe);
59734 $exe = $tmpExe;
59735 }
59736
59737 $value = rtrim(shell_exec($exe));
59738 $output->writeln('');
59739
59740 if (isset($tmpExe)) {
59741 unlink($tmpExe);
59742 }
59743
59744 return $value;
59745 }
59746
59747 if ($this->hasSttyAvailable()) {
59748 $sttyMode = shell_exec('stty -g');
59749
59750 shell_exec('stty -echo');
59751 $value = fgets($inputStream, 4096);
59752 shell_exec(sprintf('stty %s', $sttyMode));
59753
59754 if (false === $value) {
59755 throw new RuntimeException('Aborted');
59756 }
59757
59758 $value = trim($value);
59759 $output->writeln('');
59760
59761 return $value;
59762 }
59763
59764 if (false !== $shell = $this->getShell()) {
59765 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
59766 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
59767 $value = rtrim(shell_exec($command));
59768 $output->writeln('');
59769
59770 return $value;
59771 }
59772
59773 throw new RuntimeException('Unable to hide the response.');
59774 }
59775
59776
59777
59778
59779
59780
59781
59782
59783
59784
59785
59786
59787 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
59788 {
59789 $error = null;
59790 $attempts = $question->getMaxAttempts();
59791 while (null === $attempts || $attempts--) {
59792 if (null !== $error) {
59793 $this->writeError($output, $error);
59794 }
59795
59796 try {
59797 return \call_user_func($question->getValidator(), $interviewer());
59798 } catch (RuntimeException $e) {
59799 throw $e;
59800 } catch (\Exception $error) {
59801 }
59802 }
59803
59804 throw $error;
59805 }
59806
59807
59808
59809
59810
59811
59812 private function getShell()
59813 {
59814 if (null !== self::$shell) {
59815 return self::$shell;
59816 }
59817
59818 self::$shell = false;
59819
59820 if (file_exists('/usr/bin/env')) {
59821
59822 $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
59823 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
59824 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
59825 self::$shell = $sh;
59826 break;
59827 }
59828 }
59829 }
59830
59831 return self::$shell;
59832 }
59833
59834
59835
59836
59837
59838
59839 private function hasSttyAvailable()
59840 {
59841 if (null !== self::$stty) {
59842 return self::$stty;
59843 }
59844
59845 exec('stty 2>&1', $output, $exitcode);
59846
59847 return self::$stty = 0 === $exitcode;
59848 }
59849 }
59850 <?php
59851
59852
59853
59854
59855
59856
59857
59858
59859
59860
59861 namespace Symfony\Component\Console\Helper;
59862
59863 use Symfony\Component\Console\Exception\LogicException;
59864 use Symfony\Component\Console\Formatter\OutputFormatter;
59865 use Symfony\Component\Console\Input\InputInterface;
59866 use Symfony\Component\Console\Output\OutputInterface;
59867 use Symfony\Component\Console\Question\ChoiceQuestion;
59868 use Symfony\Component\Console\Question\ConfirmationQuestion;
59869 use Symfony\Component\Console\Question\Question;
59870 use Symfony\Component\Console\Style\SymfonyStyle;
59871
59872
59873
59874
59875
59876
59877 class SymfonyQuestionHelper extends QuestionHelper
59878 {
59879
59880
59881
59882 public function ask(InputInterface $input, OutputInterface $output, Question $question)
59883 {
59884 $validator = $question->getValidator();
59885 $question->setValidator(function ($value) use ($validator) {
59886 if (null !== $validator) {
59887 $value = $validator($value);
59888 } else {
59889
59890 if (!\is_array($value) && !\is_bool($value) && 0 === \strlen($value)) {
59891 throw new LogicException('A value is required.');
59892 }
59893 }
59894
59895 return $value;
59896 });
59897
59898 return parent::ask($input, $output, $question);
59899 }
59900
59901
59902
59903
59904 protected function writePrompt(OutputInterface $output, Question $question)
59905 {
59906 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
59907 $default = $question->getDefault();
59908
59909 switch (true) {
59910 case null === $default:
59911 $text = sprintf(' <info>%s</info>:', $text);
59912
59913 break;
59914
59915 case $question instanceof ConfirmationQuestion:
59916 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
59917
59918 break;
59919
59920 case $question instanceof ChoiceQuestion && $question->isMultiselect():
59921 $choices = $question->getChoices();
59922 $default = explode(',', $default);
59923
59924 foreach ($default as $key => $value) {
59925 $default[$key] = $choices[trim($value)];
59926 }
59927
59928 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
59929
59930 break;
59931
59932 case $question instanceof ChoiceQuestion:
59933 $choices = $question->getChoices();
59934 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default));
59935
59936 break;
59937
59938 default:
59939 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
59940 }
59941
59942 $output->writeln($text);
59943
59944 if ($question instanceof ChoiceQuestion) {
59945 $width = max(array_map('strlen', array_keys($question->getChoices())));
59946
59947 foreach ($question->getChoices() as $key => $value) {
59948 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
59949 }
59950 }
59951
59952 $output->write(' > ');
59953 }
59954
59955
59956
59957
59958 protected function writeError(OutputInterface $output, \Exception $error)
59959 {
59960 if ($output instanceof SymfonyStyle) {
59961 $output->newLine();
59962 $output->error($error->getMessage());
59963
59964 return;
59965 }
59966
59967 parent::writeError($output, $error);
59968 }
59969 }
59970 <?php
59971
59972
59973
59974
59975
59976
59977
59978
59979
59980
59981 namespace Symfony\Component\Console\Helper;
59982
59983 use Symfony\Component\Console\Exception\InvalidArgumentException;
59984 use Symfony\Component\Console\Output\OutputInterface;
59985
59986
59987
59988
59989
59990
59991
59992
59993
59994 class Table
59995 {
59996
59997
59998
59999 private $headers = array();
60000
60001
60002
60003
60004 private $rows = array();
60005
60006
60007
60008
60009 private $columnWidths = array();
60010
60011
60012
60013
60014
60015
60016 private $numberOfColumns;
60017
60018
60019
60020
60021 private $output;
60022
60023
60024
60025
60026 private $style;
60027
60028
60029
60030
60031 private $columnStyles = array();
60032
60033 private static $styles;
60034
60035 public function __construct(OutputInterface $output)
60036 {
60037 $this->output = $output;
60038
60039 if (!self::$styles) {
60040 self::$styles = self::initStyles();
60041 }
60042
60043 $this->setStyle('default');
60044 }
60045
60046
60047
60048
60049
60050
60051
60052 public static function setStyleDefinition($name, TableStyle $style)
60053 {
60054 if (!self::$styles) {
60055 self::$styles = self::initStyles();
60056 }
60057
60058 self::$styles[$name] = $style;
60059 }
60060
60061
60062
60063
60064
60065
60066
60067
60068 public static function getStyleDefinition($name)
60069 {
60070 if (!self::$styles) {
60071 self::$styles = self::initStyles();
60072 }
60073
60074 if (isset(self::$styles[$name])) {
60075 return self::$styles[$name];
60076 }
60077
60078 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
60079 }
60080
60081
60082
60083
60084
60085
60086
60087
60088 public function setStyle($name)
60089 {
60090 $this->style = $this->resolveStyle($name);
60091
60092 return $this;
60093 }
60094
60095
60096
60097
60098
60099
60100 public function getStyle()
60101 {
60102 return $this->style;
60103 }
60104
60105
60106
60107
60108
60109
60110
60111
60112
60113 public function setColumnStyle($columnIndex, $name)
60114 {
60115 $columnIndex = (int) $columnIndex;
60116
60117 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
60118
60119 return $this;
60120 }
60121
60122
60123
60124
60125
60126
60127
60128
60129
60130
60131 public function getColumnStyle($columnIndex)
60132 {
60133 if (isset($this->columnStyles[$columnIndex])) {
60134 return $this->columnStyles[$columnIndex];
60135 }
60136
60137 return $this->getStyle();
60138 }
60139
60140 public function setHeaders(array $headers)
60141 {
60142 $headers = array_values($headers);
60143 if (!empty($headers) && !\is_array($headers[0])) {
60144 $headers = array($headers);
60145 }
60146
60147 $this->headers = $headers;
60148
60149 return $this;
60150 }
60151
60152 public function setRows(array $rows)
60153 {
60154 $this->rows = array();
60155
60156 return $this->addRows($rows);
60157 }
60158
60159 public function addRows(array $rows)
60160 {
60161 foreach ($rows as $row) {
60162 $this->addRow($row);
60163 }
60164
60165 return $this;
60166 }
60167
60168 public function addRow($row)
60169 {
60170 if ($row instanceof TableSeparator) {
60171 $this->rows[] = $row;
60172
60173 return $this;
60174 }
60175
60176 if (!\is_array($row)) {
60177 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
60178 }
60179
60180 $this->rows[] = array_values($row);
60181
60182 return $this;
60183 }
60184
60185 public function setRow($column, array $row)
60186 {
60187 $this->rows[$column] = $row;
60188
60189 return $this;
60190 }
60191
60192
60193
60194
60195
60196
60197
60198
60199
60200
60201
60202
60203
60204
60205 public function render()
60206 {
60207 $this->calculateNumberOfColumns();
60208 $rows = $this->buildTableRows($this->rows);
60209 $headers = $this->buildTableRows($this->headers);
60210
60211 $this->calculateColumnsWidth(array_merge($headers, $rows));
60212
60213 $this->renderRowSeparator();
60214 if (!empty($headers)) {
60215 foreach ($headers as $header) {
60216 $this->renderRow($header, $this->style->getCellHeaderFormat());
60217 $this->renderRowSeparator();
60218 }
60219 }
60220 foreach ($rows as $row) {
60221 if ($row instanceof TableSeparator) {
60222 $this->renderRowSeparator();
60223 } else {
60224 $this->renderRow($row, $this->style->getCellRowFormat());
60225 }
60226 }
60227 if (!empty($rows)) {
60228 $this->renderRowSeparator();
60229 }
60230
60231 $this->cleanup();
60232 }
60233
60234
60235
60236
60237
60238
60239
60240
60241 private function renderRowSeparator()
60242 {
60243 if (0 === $count = $this->numberOfColumns) {
60244 return;
60245 }
60246
60247 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
60248 return;
60249 }
60250
60251 $markup = $this->style->getCrossingChar();
60252 for ($column = 0; $column < $count; ++$column) {
60253 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
60254 }
60255
60256 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
60257 }
60258
60259
60260
60261
60262 private function renderColumnSeparator()
60263 {
60264 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
60265 }
60266
60267
60268
60269
60270
60271
60272
60273
60274
60275
60276
60277 private function renderRow(array $row, $cellFormat)
60278 {
60279 if (empty($row)) {
60280 return;
60281 }
60282
60283 $rowContent = $this->renderColumnSeparator();
60284 foreach ($this->getRowColumns($row) as $column) {
60285 $rowContent .= $this->renderCell($row, $column, $cellFormat);
60286 $rowContent .= $this->renderColumnSeparator();
60287 }
60288 $this->output->writeln($rowContent);
60289 }
60290
60291
60292
60293
60294
60295
60296
60297
60298 private function renderCell(array $row, $column, $cellFormat)
60299 {
60300 $cell = isset($row[$column]) ? $row[$column] : '';
60301 $width = $this->columnWidths[$column];
60302 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
60303
60304 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
60305 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
60306 }
60307 }
60308
60309
60310 if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
60311 $width += \strlen($cell) - mb_strwidth($cell, $encoding);
60312 }
60313
60314 $style = $this->getColumnStyle($column);
60315
60316 if ($cell instanceof TableSeparator) {
60317 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
60318 }
60319
60320 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
60321 $content = sprintf($style->getCellRowContentFormat(), $cell);
60322
60323 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
60324 }
60325
60326
60327
60328
60329 private function calculateNumberOfColumns()
60330 {
60331 if (null !== $this->numberOfColumns) {
60332 return;
60333 }
60334
60335 $columns = array(0);
60336 foreach (array_merge($this->headers, $this->rows) as $row) {
60337 if ($row instanceof TableSeparator) {
60338 continue;
60339 }
60340
60341 $columns[] = $this->getNumberOfColumns($row);
60342 }
60343
60344 $this->numberOfColumns = max($columns);
60345 }
60346
60347 private function buildTableRows($rows)
60348 {
60349 $unmergedRows = array();
60350 for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
60351 $rows = $this->fillNextRows($rows, $rowKey);
60352
60353
60354 foreach ($rows[$rowKey] as $column => $cell) {
60355 if (!strstr($cell, "\n")) {
60356 continue;
60357 }
60358 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
60359 foreach ($lines as $lineKey => $line) {
60360 if ($cell instanceof TableCell) {
60361 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
60362 }
60363 if (0 === $lineKey) {
60364 $rows[$rowKey][$column] = $line;
60365 } else {
60366 $unmergedRows[$rowKey][$lineKey][$column] = $line;
60367 }
60368 }
60369 }
60370 }
60371
60372 $tableRows = array();
60373 foreach ($rows as $rowKey => $row) {
60374 $tableRows[] = $this->fillCells($row);
60375 if (isset($unmergedRows[$rowKey])) {
60376 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
60377 }
60378 }
60379
60380 return $tableRows;
60381 }
60382
60383
60384
60385
60386
60387
60388
60389
60390
60391 private function fillNextRows(array $rows, $line)
60392 {
60393 $unmergedRows = array();
60394 foreach ($rows[$line] as $column => $cell) {
60395 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
60396 $nbLines = $cell->getRowspan() - 1;
60397 $lines = array($cell);
60398 if (strstr($cell, "\n")) {
60399 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
60400 $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
60401
60402 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
60403 unset($lines[0]);
60404 }
60405
60406
60407 $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
60408 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
60409 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
60410 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
60411 if ($nbLines === $unmergedRowKey - $line) {
60412 break;
60413 }
60414 }
60415 }
60416 }
60417
60418 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
60419
60420 if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
60421 foreach ($unmergedRow as $cellKey => $cell) {
60422
60423 array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
60424 }
60425 } else {
60426 $row = $this->copyRow($rows, $unmergedRowKey - 1);
60427 foreach ($unmergedRow as $column => $cell) {
60428 if (!empty($cell)) {
60429 $row[$column] = $unmergedRow[$column];
60430 }
60431 }
60432 array_splice($rows, $unmergedRowKey, 0, array($row));
60433 }
60434 }
60435
60436 return $rows;
60437 }
60438
60439
60440
60441
60442
60443
60444 private function fillCells($row)
60445 {
60446 $newRow = array();
60447 foreach ($row as $column => $cell) {
60448 $newRow[] = $cell;
60449 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
60450 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
60451
60452 $newRow[] = '';
60453 }
60454 }
60455 }
60456
60457 return $newRow ?: $row;
60458 }
60459
60460
60461
60462
60463
60464
60465
60466 private function copyRow(array $rows, $line)
60467 {
60468 $row = $rows[$line];
60469 foreach ($row as $cellKey => $cellValue) {
60470 $row[$cellKey] = '';
60471 if ($cellValue instanceof TableCell) {
60472 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
60473 }
60474 }
60475
60476 return $row;
60477 }
60478
60479
60480
60481
60482
60483
60484 private function getNumberOfColumns(array $row)
60485 {
60486 $columns = \count($row);
60487 foreach ($row as $column) {
60488 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
60489 }
60490
60491 return $columns;
60492 }
60493
60494
60495
60496
60497
60498
60499 private function getRowColumns(array $row)
60500 {
60501 $columns = range(0, $this->numberOfColumns - 1);
60502 foreach ($row as $cellKey => $cell) {
60503 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
60504
60505 $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
60506 }
60507 }
60508
60509 return $columns;
60510 }
60511
60512
60513
60514
60515
60516
60517 private function calculateColumnsWidth($rows)
60518 {
60519 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
60520 $lengths = array();
60521 foreach ($rows as $row) {
60522 if ($row instanceof TableSeparator) {
60523 continue;
60524 }
60525
60526 foreach ($row as $i => $cell) {
60527 if ($cell instanceof TableCell) {
60528 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
60529 $textLength = Helper::strlen($textContent);
60530 if ($textLength > 0) {
60531 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
60532 foreach ($contentColumns as $position => $content) {
60533 $row[$i + $position] = $content;
60534 }
60535 }
60536 }
60537 }
60538
60539 $lengths[] = $this->getCellWidth($row, $column);
60540 }
60541
60542 $this->columnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2;
60543 }
60544 }
60545
60546
60547
60548
60549
60550
60551 private function getColumnSeparatorWidth()
60552 {
60553 return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
60554 }
60555
60556
60557
60558
60559
60560
60561
60562
60563
60564 private function getCellWidth(array $row, $column)
60565 {
60566 if (isset($row[$column])) {
60567 $cell = $row[$column];
60568 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
60569
60570 return $cellWidth;
60571 }
60572
60573 return 0;
60574 }
60575
60576
60577
60578
60579 private function cleanup()
60580 {
60581 $this->columnWidths = array();
60582 $this->numberOfColumns = null;
60583 }
60584
60585 private static function initStyles()
60586 {
60587 $borderless = new TableStyle();
60588 $borderless
60589 ->setHorizontalBorderChar('=')
60590 ->setVerticalBorderChar(' ')
60591 ->setCrossingChar(' ')
60592 ;
60593
60594 $compact = new TableStyle();
60595 $compact
60596 ->setHorizontalBorderChar('')
60597 ->setVerticalBorderChar(' ')
60598 ->setCrossingChar('')
60599 ->setCellRowContentFormat('%s')
60600 ;
60601
60602 $styleGuide = new TableStyle();
60603 $styleGuide
60604 ->setHorizontalBorderChar('-')
60605 ->setVerticalBorderChar(' ')
60606 ->setCrossingChar(' ')
60607 ->setCellHeaderFormat('%s')
60608 ;
60609
60610 return array(
60611 'default' => new TableStyle(),
60612 'borderless' => $borderless,
60613 'compact' => $compact,
60614 'symfony-style-guide' => $styleGuide,
60615 );
60616 }
60617
60618 private function resolveStyle($name)
60619 {
60620 if ($name instanceof TableStyle) {
60621 return $name;
60622 }
60623
60624 if (isset(self::$styles[$name])) {
60625 return self::$styles[$name];
60626 }
60627
60628 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
60629 }
60630 }
60631 <?php
60632
60633
60634
60635
60636
60637
60638
60639
60640
60641
60642 namespace Symfony\Component\Console\Helper;
60643
60644 use Symfony\Component\Console\Exception\InvalidArgumentException;
60645
60646
60647
60648
60649 class TableCell
60650 {
60651 private $value;
60652 private $options = array(
60653 'rowspan' => 1,
60654 'colspan' => 1,
60655 );
60656
60657
60658
60659
60660
60661 public function __construct($value = '', array $options = array())
60662 {
60663 if (is_numeric($value) && !\is_string($value)) {
60664 $value = (string) $value;
60665 }
60666
60667 $this->value = $value;
60668
60669
60670 if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
60671 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
60672 }
60673
60674 $this->options = array_merge($this->options, $options);
60675 }
60676
60677
60678
60679
60680
60681
60682 public function __toString()
60683 {
60684 return $this->value;
60685 }
60686
60687
60688
60689
60690
60691
60692 public function getColspan()
60693 {
60694 return (int) $this->options['colspan'];
60695 }
60696
60697
60698
60699
60700
60701
60702 public function getRowspan()
60703 {
60704 return (int) $this->options['rowspan'];
60705 }
60706 }
60707 <?php
60708
60709
60710
60711
60712
60713
60714
60715
60716
60717
60718 namespace Symfony\Component\Console\Helper;
60719
60720 use Symfony\Component\Console\Exception\InvalidArgumentException;
60721 use Symfony\Component\Console\Output\NullOutput;
60722 use Symfony\Component\Console\Output\OutputInterface;
60723
60724
60725
60726
60727
60728
60729
60730
60731
60732
60733 class TableHelper extends Helper
60734 {
60735 const LAYOUT_DEFAULT = 0;
60736 const LAYOUT_BORDERLESS = 1;
60737 const LAYOUT_COMPACT = 2;
60738
60739 private $table;
60740
60741 public function __construct($triggerDeprecationError = true)
60742 {
60743 if ($triggerDeprecationError) {
60744 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\Table class instead.', E_USER_DEPRECATED);
60745 }
60746
60747 $this->table = new Table(new NullOutput());
60748 }
60749
60750
60751
60752
60753
60754
60755
60756
60757
60758
60759 public function setLayout($layout)
60760 {
60761 switch ($layout) {
60762 case self::LAYOUT_BORDERLESS:
60763 $this->table->setStyle('borderless');
60764 break;
60765
60766 case self::LAYOUT_COMPACT:
60767 $this->table->setStyle('compact');
60768 break;
60769
60770 case self::LAYOUT_DEFAULT:
60771 $this->table->setStyle('default');
60772 break;
60773
60774 default:
60775 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
60776 }
60777
60778 return $this;
60779 }
60780
60781 public function setHeaders(array $headers)
60782 {
60783 $this->table->setHeaders($headers);
60784
60785 return $this;
60786 }
60787
60788 public function setRows(array $rows)
60789 {
60790 $this->table->setRows($rows);
60791
60792 return $this;
60793 }
60794
60795 public function addRows(array $rows)
60796 {
60797 $this->table->addRows($rows);
60798
60799 return $this;
60800 }
60801
60802 public function addRow(array $row)
60803 {
60804 $this->table->addRow($row);
60805
60806 return $this;
60807 }
60808
60809 public function setRow($column, array $row)
60810 {
60811 $this->table->setRow($column, $row);
60812
60813 return $this;
60814 }
60815
60816
60817
60818
60819
60820
60821
60822
60823 public function setPaddingChar($paddingChar)
60824 {
60825 $this->table->getStyle()->setPaddingChar($paddingChar);
60826
60827 return $this;
60828 }
60829
60830
60831
60832
60833
60834
60835
60836
60837 public function setHorizontalBorderChar($horizontalBorderChar)
60838 {
60839 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
60840
60841 return $this;
60842 }
60843
60844
60845
60846
60847
60848
60849
60850
60851 public function setVerticalBorderChar($verticalBorderChar)
60852 {
60853 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
60854
60855 return $this;
60856 }
60857
60858
60859
60860
60861
60862
60863
60864
60865 public function setCrossingChar($crossingChar)
60866 {
60867 $this->table->getStyle()->setCrossingChar($crossingChar);
60868
60869 return $this;
60870 }
60871
60872
60873
60874
60875
60876
60877
60878
60879 public function setCellHeaderFormat($cellHeaderFormat)
60880 {
60881 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
60882
60883 return $this;
60884 }
60885
60886
60887
60888
60889
60890
60891
60892
60893 public function setCellRowFormat($cellRowFormat)
60894 {
60895 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
60896
60897 return $this;
60898 }
60899
60900
60901
60902
60903
60904
60905
60906
60907 public function setCellRowContentFormat($cellRowContentFormat)
60908 {
60909 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
60910
60911 return $this;
60912 }
60913
60914
60915
60916
60917
60918
60919
60920
60921 public function setBorderFormat($borderFormat)
60922 {
60923 $this->table->getStyle()->setBorderFormat($borderFormat);
60924
60925 return $this;
60926 }
60927
60928
60929
60930
60931
60932
60933
60934
60935 public function setPadType($padType)
60936 {
60937 $this->table->getStyle()->setPadType($padType);
60938
60939 return $this;
60940 }
60941
60942
60943
60944
60945
60946
60947
60948
60949
60950
60951
60952
60953
60954 public function render(OutputInterface $output)
60955 {
60956 $p = new \ReflectionProperty($this->table, 'output');
60957 $p->setAccessible(true);
60958 $p->setValue($this->table, $output);
60959
60960 $this->table->render();
60961 }
60962
60963
60964
60965
60966 public function getName()
60967 {
60968 return 'table';
60969 }
60970 }
60971 <?php
60972
60973
60974
60975
60976
60977
60978
60979
60980
60981
60982 namespace Symfony\Component\Console\Helper;
60983
60984
60985
60986
60987
60988
60989 class TableSeparator extends TableCell
60990 {
60991 public function __construct(array $options = array())
60992 {
60993 parent::__construct('', $options);
60994 }
60995 }
60996 <?php
60997
60998
60999
61000
61001
61002
61003
61004
61005
61006
61007 namespace Symfony\Component\Console\Helper;
61008
61009 use Symfony\Component\Console\Exception\InvalidArgumentException;
61010 use Symfony\Component\Console\Exception\LogicException;
61011
61012
61013
61014
61015
61016
61017
61018 class TableStyle
61019 {
61020 private $paddingChar = ' ';
61021 private $horizontalBorderChar = '-';
61022 private $verticalBorderChar = '|';
61023 private $crossingChar = '+';
61024 private $cellHeaderFormat = '<info>%s</info>';
61025 private $cellRowFormat = '%s';
61026 private $cellRowContentFormat = ' %s ';
61027 private $borderFormat = '%s';
61028 private $padType = STR_PAD_RIGHT;
61029
61030
61031
61032
61033
61034
61035
61036
61037 public function setPaddingChar($paddingChar)
61038 {
61039 if (!$paddingChar) {
61040 throw new LogicException('The padding char must not be empty');
61041 }
61042
61043 $this->paddingChar = $paddingChar;
61044
61045 return $this;
61046 }
61047
61048
61049
61050
61051
61052
61053 public function getPaddingChar()
61054 {
61055 return $this->paddingChar;
61056 }
61057
61058
61059
61060
61061
61062
61063
61064
61065 public function setHorizontalBorderChar($horizontalBorderChar)
61066 {
61067 $this->horizontalBorderChar = $horizontalBorderChar;
61068
61069 return $this;
61070 }
61071
61072
61073
61074
61075
61076
61077 public function getHorizontalBorderChar()
61078 {
61079 return $this->horizontalBorderChar;
61080 }
61081
61082
61083
61084
61085
61086
61087
61088
61089 public function setVerticalBorderChar($verticalBorderChar)
61090 {
61091 $this->verticalBorderChar = $verticalBorderChar;
61092
61093 return $this;
61094 }
61095
61096
61097
61098
61099
61100
61101 public function getVerticalBorderChar()
61102 {
61103 return $this->verticalBorderChar;
61104 }
61105
61106
61107
61108
61109
61110
61111
61112
61113 public function setCrossingChar($crossingChar)
61114 {
61115 $this->crossingChar = $crossingChar;
61116
61117 return $this;
61118 }
61119
61120
61121
61122
61123
61124
61125 public function getCrossingChar()
61126 {
61127 return $this->crossingChar;
61128 }
61129
61130
61131
61132
61133
61134
61135
61136
61137 public function setCellHeaderFormat($cellHeaderFormat)
61138 {
61139 $this->cellHeaderFormat = $cellHeaderFormat;
61140
61141 return $this;
61142 }
61143
61144
61145
61146
61147
61148
61149 public function getCellHeaderFormat()
61150 {
61151 return $this->cellHeaderFormat;
61152 }
61153
61154
61155
61156
61157
61158
61159
61160
61161 public function setCellRowFormat($cellRowFormat)
61162 {
61163 $this->cellRowFormat = $cellRowFormat;
61164
61165 return $this;
61166 }
61167
61168
61169
61170
61171
61172
61173 public function getCellRowFormat()
61174 {
61175 return $this->cellRowFormat;
61176 }
61177
61178
61179
61180
61181
61182
61183
61184
61185 public function setCellRowContentFormat($cellRowContentFormat)
61186 {
61187 $this->cellRowContentFormat = $cellRowContentFormat;
61188
61189 return $this;
61190 }
61191
61192
61193
61194
61195
61196
61197 public function getCellRowContentFormat()
61198 {
61199 return $this->cellRowContentFormat;
61200 }
61201
61202
61203
61204
61205
61206
61207
61208
61209 public function setBorderFormat($borderFormat)
61210 {
61211 $this->borderFormat = $borderFormat;
61212
61213 return $this;
61214 }
61215
61216
61217
61218
61219
61220
61221 public function getBorderFormat()
61222 {
61223 return $this->borderFormat;
61224 }
61225
61226
61227
61228
61229
61230
61231
61232
61233 public function setPadType($padType)
61234 {
61235 if (!\in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
61236 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
61237 }
61238
61239 $this->padType = $padType;
61240
61241 return $this;
61242 }
61243
61244
61245
61246
61247
61248
61249 public function getPadType()
61250 {
61251 return $this->padType;
61252 }
61253 }
61254 <?php
61255
61256
61257
61258
61259
61260
61261
61262
61263
61264
61265 namespace Symfony\Component\Console\Input;
61266
61267 use Symfony\Component\Console\Exception\RuntimeException;
61268
61269
61270
61271
61272
61273
61274
61275
61276
61277
61278
61279
61280
61281
61282
61283
61284
61285
61286
61287
61288
61289
61290
61291
61292
61293
61294 class ArgvInput extends Input
61295 {
61296 private $tokens;
61297 private $parsed;
61298
61299
61300
61301
61302
61303 public function __construct(array $argv = null, InputDefinition $definition = null)
61304 {
61305 if (null === $argv) {
61306 $argv = $_SERVER['argv'];
61307 }
61308
61309
61310 array_shift($argv);
61311
61312 $this->tokens = $argv;
61313
61314 parent::__construct($definition);
61315 }
61316
61317 protected function setTokens(array $tokens)
61318 {
61319 $this->tokens = $tokens;
61320 }
61321
61322
61323
61324
61325 protected function parse()
61326 {
61327 $parseOptions = true;
61328 $this->parsed = $this->tokens;
61329 while (null !== $token = array_shift($this->parsed)) {
61330 if ($parseOptions && '' == $token) {
61331 $this->parseArgument($token);
61332 } elseif ($parseOptions && '--' == $token) {
61333 $parseOptions = false;
61334 } elseif ($parseOptions && 0 === strpos($token, '--')) {
61335 $this->parseLongOption($token);
61336 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
61337 $this->parseShortOption($token);
61338 } else {
61339 $this->parseArgument($token);
61340 }
61341 }
61342 }
61343
61344
61345
61346
61347
61348
61349 private function parseShortOption($token)
61350 {
61351 $name = substr($token, 1);
61352
61353 if (\strlen($name) > 1) {
61354 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
61355
61356 $this->addShortOption($name[0], substr($name, 1));
61357 } else {
61358 $this->parseShortOptionSet($name);
61359 }
61360 } else {
61361 $this->addShortOption($name, null);
61362 }
61363 }
61364
61365
61366
61367
61368
61369
61370
61371
61372 private function parseShortOptionSet($name)
61373 {
61374 $len = \strlen($name);
61375 for ($i = 0; $i < $len; ++$i) {
61376 if (!$this->definition->hasShortcut($name[$i])) {
61377 $encoding = mb_detect_encoding($name, null, true);
61378 throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
61379 }
61380
61381 $option = $this->definition->getOptionForShortcut($name[$i]);
61382 if ($option->acceptValue()) {
61383 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
61384
61385 break;
61386 } else {
61387 $this->addLongOption($option->getName(), null);
61388 }
61389 }
61390 }
61391
61392
61393
61394
61395
61396
61397 private function parseLongOption($token)
61398 {
61399 $name = substr($token, 2);
61400
61401 if (false !== $pos = strpos($name, '=')) {
61402 if (0 === \strlen($value = substr($name, $pos + 1))) {
61403 array_unshift($this->parsed, null);
61404 }
61405 $this->addLongOption(substr($name, 0, $pos), $value);
61406 } else {
61407 $this->addLongOption($name, null);
61408 }
61409 }
61410
61411
61412
61413
61414
61415
61416
61417
61418 private function parseArgument($token)
61419 {
61420 $c = \count($this->arguments);
61421
61422
61423 if ($this->definition->hasArgument($c)) {
61424 $arg = $this->definition->getArgument($c);
61425 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
61426
61427
61428 } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
61429 $arg = $this->definition->getArgument($c - 1);
61430 $this->arguments[$arg->getName()][] = $token;
61431
61432
61433 } else {
61434 $all = $this->definition->getArguments();
61435 if (\count($all)) {
61436 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
61437 }
61438
61439 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
61440 }
61441 }
61442
61443
61444
61445
61446
61447
61448
61449
61450
61451 private function addShortOption($shortcut, $value)
61452 {
61453 if (!$this->definition->hasShortcut($shortcut)) {
61454 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
61455 }
61456
61457 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
61458 }
61459
61460
61461
61462
61463
61464
61465
61466
61467
61468 private function addLongOption($name, $value)
61469 {
61470 if (!$this->definition->hasOption($name)) {
61471 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
61472 }
61473
61474 $option = $this->definition->getOption($name);
61475
61476
61477 if (!isset($value[0])) {
61478 $value = null;
61479 }
61480
61481 if (null !== $value && !$option->acceptValue()) {
61482 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
61483 }
61484
61485 if (null === $value && $option->acceptValue() && \count($this->parsed)) {
61486
61487
61488 $next = array_shift($this->parsed);
61489 if (isset($next[0]) && '-' !== $next[0]) {
61490 $value = $next;
61491 } elseif (empty($next)) {
61492 $value = null;
61493 } else {
61494 array_unshift($this->parsed, $next);
61495 }
61496 }
61497
61498 if (null === $value) {
61499 if ($option->isValueRequired()) {
61500 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
61501 }
61502
61503 if (!$option->isArray()) {
61504 $value = $option->isValueOptional() ? $option->getDefault() : true;
61505 }
61506 }
61507
61508 if ($option->isArray()) {
61509 $this->options[$name][] = $value;
61510 } else {
61511 $this->options[$name] = $value;
61512 }
61513 }
61514
61515
61516
61517
61518 public function getFirstArgument()
61519 {
61520 foreach ($this->tokens as $token) {
61521 if ($token && '-' === $token[0]) {
61522 continue;
61523 }
61524
61525 return $token;
61526 }
61527 }
61528
61529
61530
61531
61532 public function hasParameterOption($values)
61533 {
61534 $values = (array) $values;
61535
61536 foreach ($this->tokens as $token) {
61537 foreach ($values as $value) {
61538
61539
61540
61541 $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
61542 if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
61543 return true;
61544 }
61545 }
61546 }
61547
61548 return false;
61549 }
61550
61551
61552
61553
61554 public function getParameterOption($values, $default = false)
61555 {
61556 $values = (array) $values;
61557 $tokens = $this->tokens;
61558
61559 while (0 < \count($tokens)) {
61560 $token = array_shift($tokens);
61561
61562 foreach ($values as $value) {
61563 if ($token === $value) {
61564 return array_shift($tokens);
61565 }
61566
61567
61568
61569 $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
61570 if ('' !== $leading && 0 === strpos($token, $leading)) {
61571 return substr($token, \strlen($leading));
61572 }
61573 }
61574 }
61575
61576 return $default;
61577 }
61578
61579
61580
61581
61582
61583
61584 public function __toString()
61585 {
61586 $self = $this;
61587 $tokens = array_map(function ($token) use ($self) {
61588 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
61589 return $match[1].$self->escapeToken($match[2]);
61590 }
61591
61592 if ($token && '-' !== $token[0]) {
61593 return $self->escapeToken($token);
61594 }
61595
61596 return $token;
61597 }, $this->tokens);
61598
61599 return implode(' ', $tokens);
61600 }
61601 }
61602 <?php
61603
61604
61605
61606
61607
61608
61609
61610
61611
61612
61613 namespace Symfony\Component\Console\Input;
61614
61615 use Symfony\Component\Console\Exception\InvalidArgumentException;
61616 use Symfony\Component\Console\Exception\InvalidOptionException;
61617
61618
61619
61620
61621
61622
61623
61624
61625
61626
61627 class ArrayInput extends Input
61628 {
61629 private $parameters;
61630
61631 public function __construct(array $parameters, InputDefinition $definition = null)
61632 {
61633 $this->parameters = $parameters;
61634
61635 parent::__construct($definition);
61636 }
61637
61638
61639
61640
61641 public function getFirstArgument()
61642 {
61643 foreach ($this->parameters as $key => $value) {
61644 if ($key && '-' === $key[0]) {
61645 continue;
61646 }
61647
61648 return $value;
61649 }
61650 }
61651
61652
61653
61654
61655 public function hasParameterOption($values)
61656 {
61657 $values = (array) $values;
61658
61659 foreach ($this->parameters as $k => $v) {
61660 if (!\is_int($k)) {
61661 $v = $k;
61662 }
61663
61664 if (\in_array($v, $values)) {
61665 return true;
61666 }
61667 }
61668
61669 return false;
61670 }
61671
61672
61673
61674
61675 public function getParameterOption($values, $default = false)
61676 {
61677 $values = (array) $values;
61678
61679 foreach ($this->parameters as $k => $v) {
61680 if (\is_int($k)) {
61681 if (\in_array($v, $values)) {
61682 return true;
61683 }
61684 } elseif (\in_array($k, $values)) {
61685 return $v;
61686 }
61687 }
61688
61689 return $default;
61690 }
61691
61692
61693
61694
61695
61696
61697 public function __toString()
61698 {
61699 $params = array();
61700 foreach ($this->parameters as $param => $val) {
61701 if ($param && '-' === $param[0]) {
61702 if (\is_array($val)) {
61703 foreach ($val as $v) {
61704 $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
61705 }
61706 } else {
61707 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
61708 }
61709 } else {
61710 $params[] = \is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val);
61711 }
61712 }
61713
61714 return implode(' ', $params);
61715 }
61716
61717
61718
61719
61720 protected function parse()
61721 {
61722 foreach ($this->parameters as $key => $value) {
61723 if (0 === strpos($key, '--')) {
61724 $this->addLongOption(substr($key, 2), $value);
61725 } elseif ('-' === $key[0]) {
61726 $this->addShortOption(substr($key, 1), $value);
61727 } else {
61728 $this->addArgument($key, $value);
61729 }
61730 }
61731 }
61732
61733
61734
61735
61736
61737
61738
61739
61740
61741 private function addShortOption($shortcut, $value)
61742 {
61743 if (!$this->definition->hasShortcut($shortcut)) {
61744 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
61745 }
61746
61747 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
61748 }
61749
61750
61751
61752
61753
61754
61755
61756
61757
61758
61759 private function addLongOption($name, $value)
61760 {
61761 if (!$this->definition->hasOption($name)) {
61762 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
61763 }
61764
61765 $option = $this->definition->getOption($name);
61766
61767 if (null === $value) {
61768 if ($option->isValueRequired()) {
61769 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
61770 }
61771
61772 $value = $option->isValueOptional() ? $option->getDefault() : true;
61773 }
61774
61775 $this->options[$name] = $value;
61776 }
61777
61778
61779
61780
61781
61782
61783
61784
61785
61786 private function addArgument($name, $value)
61787 {
61788 if (!$this->definition->hasArgument($name)) {
61789 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
61790 }
61791
61792 $this->arguments[$name] = $value;
61793 }
61794 }
61795 <?php
61796
61797
61798
61799
61800
61801
61802
61803
61804
61805
61806 namespace Symfony\Component\Console\Input;
61807
61808 use Symfony\Component\Console\Exception\InvalidArgumentException;
61809 use Symfony\Component\Console\Exception\RuntimeException;
61810
61811
61812
61813
61814
61815
61816
61817
61818
61819
61820
61821
61822 abstract class Input implements InputInterface
61823 {
61824 protected $definition;
61825 protected $options = array();
61826 protected $arguments = array();
61827 protected $interactive = true;
61828
61829 public function __construct(InputDefinition $definition = null)
61830 {
61831 if (null === $definition) {
61832 $this->definition = new InputDefinition();
61833 } else {
61834 $this->bind($definition);
61835 $this->validate();
61836 }
61837 }
61838
61839
61840
61841
61842 public function bind(InputDefinition $definition)
61843 {
61844 $this->arguments = array();
61845 $this->options = array();
61846 $this->definition = $definition;
61847
61848 $this->parse();
61849 }
61850
61851
61852
61853
61854 abstract protected function parse();
61855
61856
61857
61858
61859 public function validate()
61860 {
61861 $definition = $this->definition;
61862 $givenArguments = $this->arguments;
61863
61864 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
61865 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
61866 });
61867
61868 if (\count($missingArguments) > 0) {
61869 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
61870 }
61871 }
61872
61873
61874
61875
61876 public function isInteractive()
61877 {
61878 return $this->interactive;
61879 }
61880
61881
61882
61883
61884 public function setInteractive($interactive)
61885 {
61886 $this->interactive = (bool) $interactive;
61887 }
61888
61889
61890
61891
61892 public function getArguments()
61893 {
61894 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
61895 }
61896
61897
61898
61899
61900 public function getArgument($name)
61901 {
61902 if (!$this->definition->hasArgument($name)) {
61903 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
61904 }
61905
61906 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
61907 }
61908
61909
61910
61911
61912 public function setArgument($name, $value)
61913 {
61914 if (!$this->definition->hasArgument($name)) {
61915 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
61916 }
61917
61918 $this->arguments[$name] = $value;
61919 }
61920
61921
61922
61923
61924 public function hasArgument($name)
61925 {
61926 return $this->definition->hasArgument($name);
61927 }
61928
61929
61930
61931
61932 public function getOptions()
61933 {
61934 return array_merge($this->definition->getOptionDefaults(), $this->options);
61935 }
61936
61937
61938
61939
61940 public function getOption($name)
61941 {
61942 if (!$this->definition->hasOption($name)) {
61943 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
61944 }
61945
61946 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
61947 }
61948
61949
61950
61951
61952 public function setOption($name, $value)
61953 {
61954 if (!$this->definition->hasOption($name)) {
61955 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
61956 }
61957
61958 $this->options[$name] = $value;
61959 }
61960
61961
61962
61963
61964 public function hasOption($name)
61965 {
61966 return $this->definition->hasOption($name);
61967 }
61968
61969
61970
61971
61972
61973
61974
61975
61976 public function escapeToken($token)
61977 {
61978 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
61979 }
61980 }
61981 <?php
61982
61983
61984
61985
61986
61987
61988
61989
61990
61991
61992 namespace Symfony\Component\Console\Input;
61993
61994 use Symfony\Component\Console\Exception\InvalidArgumentException;
61995 use Symfony\Component\Console\Exception\LogicException;
61996
61997
61998
61999
62000
62001
62002 class InputArgument
62003 {
62004 const REQUIRED = 1;
62005 const OPTIONAL = 2;
62006 const IS_ARRAY = 4;
62007
62008 private $name;
62009 private $mode;
62010 private $default;
62011 private $description;
62012
62013
62014
62015
62016
62017
62018
62019
62020
62021 public function __construct($name, $mode = null, $description = '', $default = null)
62022 {
62023 if (null === $mode) {
62024 $mode = self::OPTIONAL;
62025 } elseif (!\is_int($mode) || $mode > 7 || $mode < 1) {
62026 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
62027 }
62028
62029 $this->name = $name;
62030 $this->mode = $mode;
62031 $this->description = $description;
62032
62033 $this->setDefault($default);
62034 }
62035
62036
62037
62038
62039
62040
62041 public function getName()
62042 {
62043 return $this->name;
62044 }
62045
62046
62047
62048
62049
62050
62051 public function isRequired()
62052 {
62053 return self::REQUIRED === (self::REQUIRED & $this->mode);
62054 }
62055
62056
62057
62058
62059
62060
62061 public function isArray()
62062 {
62063 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
62064 }
62065
62066
62067
62068
62069
62070
62071
62072
62073 public function setDefault($default = null)
62074 {
62075 if (self::REQUIRED === $this->mode && null !== $default) {
62076 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
62077 }
62078
62079 if ($this->isArray()) {
62080 if (null === $default) {
62081 $default = array();
62082 } elseif (!\is_array($default)) {
62083 throw new LogicException('A default value for an array argument must be an array.');
62084 }
62085 }
62086
62087 $this->default = $default;
62088 }
62089
62090
62091
62092
62093
62094
62095 public function getDefault()
62096 {
62097 return $this->default;
62098 }
62099
62100
62101
62102
62103
62104
62105 public function getDescription()
62106 {
62107 return $this->description;
62108 }
62109 }
62110 <?php
62111
62112
62113
62114
62115
62116
62117
62118
62119
62120
62121 namespace Symfony\Component\Console\Input;
62122
62123
62124
62125
62126
62127
62128
62129 interface InputAwareInterface
62130 {
62131
62132
62133
62134 public function setInput(InputInterface $input);
62135 }
62136 <?php
62137
62138
62139
62140
62141
62142
62143
62144
62145
62146
62147 namespace Symfony\Component\Console\Input;
62148
62149 use Symfony\Component\Console\Descriptor\TextDescriptor;
62150 use Symfony\Component\Console\Descriptor\XmlDescriptor;
62151 use Symfony\Component\Console\Exception\InvalidArgumentException;
62152 use Symfony\Component\Console\Exception\LogicException;
62153 use Symfony\Component\Console\Output\BufferedOutput;
62154
62155
62156
62157
62158
62159
62160
62161
62162
62163
62164
62165
62166
62167 class InputDefinition
62168 {
62169 private $arguments;
62170 private $requiredCount;
62171 private $hasAnArrayArgument = false;
62172 private $hasOptional;
62173 private $options;
62174 private $shortcuts;
62175
62176
62177
62178
62179 public function __construct(array $definition = array())
62180 {
62181 $this->setDefinition($definition);
62182 }
62183
62184
62185
62186
62187 public function setDefinition(array $definition)
62188 {
62189 $arguments = array();
62190 $options = array();
62191 foreach ($definition as $item) {
62192 if ($item instanceof InputOption) {
62193 $options[] = $item;
62194 } else {
62195 $arguments[] = $item;
62196 }
62197 }
62198
62199 $this->setArguments($arguments);
62200 $this->setOptions($options);
62201 }
62202
62203
62204
62205
62206
62207
62208 public function setArguments($arguments = array())
62209 {
62210 $this->arguments = array();
62211 $this->requiredCount = 0;
62212 $this->hasOptional = false;
62213 $this->hasAnArrayArgument = false;
62214 $this->addArguments($arguments);
62215 }
62216
62217
62218
62219
62220
62221
62222 public function addArguments($arguments = array())
62223 {
62224 if (null !== $arguments) {
62225 foreach ($arguments as $argument) {
62226 $this->addArgument($argument);
62227 }
62228 }
62229 }
62230
62231
62232
62233
62234 public function addArgument(InputArgument $argument)
62235 {
62236 if (isset($this->arguments[$argument->getName()])) {
62237 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
62238 }
62239
62240 if ($this->hasAnArrayArgument) {
62241 throw new LogicException('Cannot add an argument after an array argument.');
62242 }
62243
62244 if ($argument->isRequired() && $this->hasOptional) {
62245 throw new LogicException('Cannot add a required argument after an optional one.');
62246 }
62247
62248 if ($argument->isArray()) {
62249 $this->hasAnArrayArgument = true;
62250 }
62251
62252 if ($argument->isRequired()) {
62253 ++$this->requiredCount;
62254 } else {
62255 $this->hasOptional = true;
62256 }
62257
62258 $this->arguments[$argument->getName()] = $argument;
62259 }
62260
62261
62262
62263
62264
62265
62266
62267
62268
62269
62270 public function getArgument($name)
62271 {
62272 if (!$this->hasArgument($name)) {
62273 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
62274 }
62275
62276 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
62277
62278 return $arguments[$name];
62279 }
62280
62281
62282
62283
62284
62285
62286
62287
62288 public function hasArgument($name)
62289 {
62290 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
62291
62292 return isset($arguments[$name]);
62293 }
62294
62295
62296
62297
62298
62299
62300 public function getArguments()
62301 {
62302 return $this->arguments;
62303 }
62304
62305
62306
62307
62308
62309
62310 public function getArgumentCount()
62311 {
62312 return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments);
62313 }
62314
62315
62316
62317
62318
62319
62320 public function getArgumentRequiredCount()
62321 {
62322 return $this->requiredCount;
62323 }
62324
62325
62326
62327
62328
62329
62330 public function getArgumentDefaults()
62331 {
62332 $values = array();
62333 foreach ($this->arguments as $argument) {
62334 $values[$argument->getName()] = $argument->getDefault();
62335 }
62336
62337 return $values;
62338 }
62339
62340
62341
62342
62343
62344
62345 public function setOptions($options = array())
62346 {
62347 $this->options = array();
62348 $this->shortcuts = array();
62349 $this->addOptions($options);
62350 }
62351
62352
62353
62354
62355
62356
62357 public function addOptions($options = array())
62358 {
62359 foreach ($options as $option) {
62360 $this->addOption($option);
62361 }
62362 }
62363
62364
62365
62366
62367 public function addOption(InputOption $option)
62368 {
62369 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
62370 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
62371 }
62372
62373 if ($option->getShortcut()) {
62374 foreach (explode('|', $option->getShortcut()) as $shortcut) {
62375 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
62376 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
62377 }
62378 }
62379 }
62380
62381 $this->options[$option->getName()] = $option;
62382 if ($option->getShortcut()) {
62383 foreach (explode('|', $option->getShortcut()) as $shortcut) {
62384 $this->shortcuts[$shortcut] = $option->getName();
62385 }
62386 }
62387 }
62388
62389
62390
62391
62392
62393
62394
62395
62396
62397
62398 public function getOption($name)
62399 {
62400 if (!$this->hasOption($name)) {
62401 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
62402 }
62403
62404 return $this->options[$name];
62405 }
62406
62407
62408
62409
62410
62411
62412
62413
62414
62415
62416
62417 public function hasOption($name)
62418 {
62419 return isset($this->options[$name]);
62420 }
62421
62422
62423
62424
62425
62426
62427 public function getOptions()
62428 {
62429 return $this->options;
62430 }
62431
62432
62433
62434
62435
62436
62437
62438
62439 public function hasShortcut($name)
62440 {
62441 return isset($this->shortcuts[$name]);
62442 }
62443
62444
62445
62446
62447
62448
62449
62450
62451 public function getOptionForShortcut($shortcut)
62452 {
62453 return $this->getOption($this->shortcutToName($shortcut));
62454 }
62455
62456
62457
62458
62459
62460
62461 public function getOptionDefaults()
62462 {
62463 $values = array();
62464 foreach ($this->options as $option) {
62465 $values[$option->getName()] = $option->getDefault();
62466 }
62467
62468 return $values;
62469 }
62470
62471
62472
62473
62474
62475
62476
62477
62478
62479
62480 private function shortcutToName($shortcut)
62481 {
62482 if (!isset($this->shortcuts[$shortcut])) {
62483 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
62484 }
62485
62486 return $this->shortcuts[$shortcut];
62487 }
62488
62489
62490
62491
62492
62493
62494
62495
62496 public function getSynopsis($short = false)
62497 {
62498 $elements = array();
62499
62500 if ($short && $this->getOptions()) {
62501 $elements[] = '[options]';
62502 } elseif (!$short) {
62503 foreach ($this->getOptions() as $option) {
62504 $value = '';
62505 if ($option->acceptValue()) {
62506 $value = sprintf(
62507 ' %s%s%s',
62508 $option->isValueOptional() ? '[' : '',
62509 strtoupper($option->getName()),
62510 $option->isValueOptional() ? ']' : ''
62511 );
62512 }
62513
62514 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
62515 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
62516 }
62517 }
62518
62519 if (\count($elements) && $this->getArguments()) {
62520 $elements[] = '[--]';
62521 }
62522
62523 foreach ($this->getArguments() as $argument) {
62524 $element = '<'.$argument->getName().'>';
62525 if (!$argument->isRequired()) {
62526 $element = '['.$element.']';
62527 } elseif ($argument->isArray()) {
62528 $element .= ' ('.$element.')';
62529 }
62530
62531 if ($argument->isArray()) {
62532 $element .= '...';
62533 }
62534
62535 $elements[] = $element;
62536 }
62537
62538 return implode(' ', $elements);
62539 }
62540
62541
62542
62543
62544
62545
62546
62547
62548 public function asText()
62549 {
62550 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
62551
62552 $descriptor = new TextDescriptor();
62553 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
62554 $descriptor->describe($output, $this, array('raw_output' => true));
62555
62556 return $output->fetch();
62557 }
62558
62559
62560
62561
62562
62563
62564
62565
62566
62567
62568 public function asXml($asDom = false)
62569 {
62570 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
62571
62572 $descriptor = new XmlDescriptor();
62573
62574 if ($asDom) {
62575 return $descriptor->getInputDefinitionDocument($this);
62576 }
62577
62578 $output = new BufferedOutput();
62579 $descriptor->describe($output, $this);
62580
62581 return $output->fetch();
62582 }
62583 }
62584 <?php
62585
62586
62587
62588
62589
62590
62591
62592
62593
62594
62595 namespace Symfony\Component\Console\Input;
62596
62597 use Symfony\Component\Console\Exception\InvalidArgumentException;
62598 use Symfony\Component\Console\Exception\RuntimeException;
62599
62600
62601
62602
62603
62604
62605 interface InputInterface
62606 {
62607
62608
62609
62610
62611
62612 public function getFirstArgument();
62613
62614
62615
62616
62617
62618
62619
62620
62621
62622
62623
62624
62625
62626 public function hasParameterOption($values);
62627
62628
62629
62630
62631
62632
62633
62634
62635
62636
62637
62638
62639
62640
62641 public function getParameterOption($values, $default = false);
62642
62643
62644
62645
62646
62647
62648 public function bind(InputDefinition $definition);
62649
62650
62651
62652
62653
62654
62655 public function validate();
62656
62657
62658
62659
62660
62661
62662 public function getArguments();
62663
62664
62665
62666
62667
62668
62669
62670
62671
62672
62673 public function getArgument($name);
62674
62675
62676
62677
62678
62679
62680
62681
62682
62683 public function setArgument($name, $value);
62684
62685
62686
62687
62688
62689
62690
62691
62692 public function hasArgument($name);
62693
62694
62695
62696
62697
62698
62699 public function getOptions();
62700
62701
62702
62703
62704
62705
62706
62707
62708
62709
62710 public function getOption($name);
62711
62712
62713
62714
62715
62716
62717
62718
62719
62720 public function setOption($name, $value);
62721
62722
62723
62724
62725
62726
62727
62728
62729 public function hasOption($name);
62730
62731
62732
62733
62734
62735
62736 public function isInteractive();
62737
62738
62739
62740
62741
62742
62743 public function setInteractive($interactive);
62744 }
62745 <?php
62746
62747
62748
62749
62750
62751
62752
62753
62754
62755
62756 namespace Symfony\Component\Console\Input;
62757
62758 use Symfony\Component\Console\Exception\InvalidArgumentException;
62759 use Symfony\Component\Console\Exception\LogicException;
62760
62761
62762
62763
62764
62765
62766 class InputOption
62767 {
62768 const VALUE_NONE = 1;
62769 const VALUE_REQUIRED = 2;
62770 const VALUE_OPTIONAL = 4;
62771 const VALUE_IS_ARRAY = 8;
62772
62773 private $name;
62774 private $shortcut;
62775 private $mode;
62776 private $default;
62777 private $description;
62778
62779
62780
62781
62782
62783
62784
62785
62786
62787
62788 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
62789 {
62790 if (0 === strpos($name, '--')) {
62791 $name = substr($name, 2);
62792 }
62793
62794 if (empty($name)) {
62795 throw new InvalidArgumentException('An option name cannot be empty.');
62796 }
62797
62798 if (empty($shortcut)) {
62799 $shortcut = null;
62800 }
62801
62802 if (null !== $shortcut) {
62803 if (\is_array($shortcut)) {
62804 $shortcut = implode('|', $shortcut);
62805 }
62806 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
62807 $shortcuts = array_filter($shortcuts);
62808 $shortcut = implode('|', $shortcuts);
62809
62810 if (empty($shortcut)) {
62811 throw new InvalidArgumentException('An option shortcut cannot be empty.');
62812 }
62813 }
62814
62815 if (null === $mode) {
62816 $mode = self::VALUE_NONE;
62817 } elseif (!\is_int($mode) || $mode > 15 || $mode < 1) {
62818 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
62819 }
62820
62821 $this->name = $name;
62822 $this->shortcut = $shortcut;
62823 $this->mode = $mode;
62824 $this->description = $description;
62825
62826 if ($this->isArray() && !$this->acceptValue()) {
62827 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
62828 }
62829
62830 $this->setDefault($default);
62831 }
62832
62833
62834
62835
62836
62837
62838 public function getShortcut()
62839 {
62840 return $this->shortcut;
62841 }
62842
62843
62844
62845
62846
62847
62848 public function getName()
62849 {
62850 return $this->name;
62851 }
62852
62853
62854
62855
62856
62857
62858 public function acceptValue()
62859 {
62860 return $this->isValueRequired() || $this->isValueOptional();
62861 }
62862
62863
62864
62865
62866
62867
62868 public function isValueRequired()
62869 {
62870 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
62871 }
62872
62873
62874
62875
62876
62877
62878 public function isValueOptional()
62879 {
62880 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
62881 }
62882
62883
62884
62885
62886
62887
62888 public function isArray()
62889 {
62890 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
62891 }
62892
62893
62894
62895
62896
62897
62898
62899
62900 public function setDefault($default = null)
62901 {
62902 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
62903 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
62904 }
62905
62906 if ($this->isArray()) {
62907 if (null === $default) {
62908 $default = array();
62909 } elseif (!\is_array($default)) {
62910 throw new LogicException('A default value for an array option must be an array.');
62911 }
62912 }
62913
62914 $this->default = $this->acceptValue() ? $default : false;
62915 }
62916
62917
62918
62919
62920
62921
62922 public function getDefault()
62923 {
62924 return $this->default;
62925 }
62926
62927
62928
62929
62930
62931
62932 public function getDescription()
62933 {
62934 return $this->description;
62935 }
62936
62937
62938
62939
62940
62941
62942 public function equals(self $option)
62943 {
62944 return $option->getName() === $this->getName()
62945 && $option->getShortcut() === $this->getShortcut()
62946 && $option->getDefault() === $this->getDefault()
62947 && $option->isArray() === $this->isArray()
62948 && $option->isValueRequired() === $this->isValueRequired()
62949 && $option->isValueOptional() === $this->isValueOptional()
62950 ;
62951 }
62952 }
62953 <?php
62954
62955
62956
62957
62958
62959
62960
62961
62962
62963
62964 namespace Symfony\Component\Console\Input;
62965
62966 use Symfony\Component\Console\Exception\InvalidArgumentException;
62967
62968
62969
62970
62971
62972
62973
62974
62975
62976
62977 class StringInput extends ArgvInput
62978 {
62979 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
62980 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
62981
62982
62983
62984
62985
62986
62987
62988 public function __construct($input, InputDefinition $definition = null)
62989 {
62990 if ($definition) {
62991 @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);
62992 }
62993
62994 parent::__construct(array(), null);
62995
62996 $this->setTokens($this->tokenize($input));
62997
62998 if (null !== $definition) {
62999 $this->bind($definition);
63000 }
63001 }
63002
63003
63004
63005
63006
63007
63008
63009
63010
63011
63012 private function tokenize($input)
63013 {
63014 $tokens = array();
63015 $length = \strlen($input);
63016 $cursor = 0;
63017 while ($cursor < $length) {
63018 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
63019 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
63020 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, \strlen($match[3]) - 2)));
63021 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
63022 $tokens[] = stripcslashes(substr($match[0], 1, \strlen($match[0]) - 2));
63023 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
63024 $tokens[] = stripcslashes($match[1]);
63025 } else {
63026
63027 throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
63028 }
63029
63030 $cursor += \strlen($match[0]);
63031 }
63032
63033 return $tokens;
63034 }
63035 }
63036 Copyright (c) 2004-2018 Fabien Potencier
63037
63038 Permission is hereby granted, free of charge, to any person obtaining a copy
63039 of this software and associated documentation files (the "Software"), to deal
63040 in the Software without restriction, including without limitation the rights
63041 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63042 copies of the Software, and to permit persons to whom the Software is furnished
63043 to do so, subject to the following conditions:
63044
63045 The above copyright notice and this permission notice shall be included in all
63046 copies or substantial portions of the Software.
63047
63048 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63049 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63050 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63051 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63052 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63053 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63054 THE SOFTWARE.
63055 <?php
63056
63057
63058
63059
63060
63061
63062
63063
63064
63065
63066 namespace Symfony\Component\Console\Logger;
63067
63068 use Psr\Log\AbstractLogger;
63069 use Psr\Log\InvalidArgumentException;
63070 use Psr\Log\LogLevel;
63071 use Symfony\Component\Console\Output\ConsoleOutputInterface;
63072 use Symfony\Component\Console\Output\OutputInterface;
63073
63074
63075
63076
63077
63078
63079
63080
63081 class ConsoleLogger extends AbstractLogger
63082 {
63083 const INFO = 'info';
63084 const ERROR = 'error';
63085
63086 private $output;
63087 private $verbosityLevelMap = array(
63088 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
63089 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
63090 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
63091 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
63092 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
63093 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
63094 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
63095 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
63096 );
63097 private $formatLevelMap = array(
63098 LogLevel::EMERGENCY => self::ERROR,
63099 LogLevel::ALERT => self::ERROR,
63100 LogLevel::CRITICAL => self::ERROR,
63101 LogLevel::ERROR => self::ERROR,
63102 LogLevel::WARNING => self::INFO,
63103 LogLevel::NOTICE => self::INFO,
63104 LogLevel::INFO => self::INFO,
63105 LogLevel::DEBUG => self::INFO,
63106 );
63107
63108 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
63109 {
63110 $this->output = $output;
63111 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
63112 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
63113 }
63114
63115
63116
63117
63118 public function log($level, $message, array $context = array())
63119 {
63120 if (!isset($this->verbosityLevelMap[$level])) {
63121 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
63122 }
63123
63124
63125 if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) {
63126 $output = $this->output->getErrorOutput();
63127 } else {
63128 $output = $this->output;
63129 }
63130
63131 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
63132 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
63133 }
63134 }
63135
63136
63137
63138
63139
63140
63141
63142
63143
63144
63145
63146 private function interpolate($message, array $context)
63147 {
63148
63149 $replace = array();
63150 foreach ($context as $key => $val) {
63151 if (!\is_array($val) && (!\is_object($val) || method_exists($val, '__toString'))) {
63152 $replace[sprintf('{%s}', $key)] = $val;
63153 }
63154 }
63155
63156
63157 return strtr($message, $replace);
63158 }
63159 }
63160 <?php
63161
63162
63163
63164
63165
63166
63167
63168
63169
63170
63171 namespace Symfony\Component\Console\Output;
63172
63173
63174
63175
63176 class BufferedOutput extends Output
63177 {
63178 private $buffer = '';
63179
63180
63181
63182
63183
63184
63185 public function fetch()
63186 {
63187 $content = $this->buffer;
63188 $this->buffer = '';
63189
63190 return $content;
63191 }
63192
63193
63194
63195
63196 protected function doWrite($message, $newline)
63197 {
63198 $this->buffer .= $message;
63199
63200 if ($newline) {
63201 $this->buffer .= PHP_EOL;
63202 }
63203 }
63204 }
63205 <?php
63206
63207
63208
63209
63210
63211
63212
63213
63214
63215
63216 namespace Symfony\Component\Console\Output;
63217
63218 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
63219
63220
63221
63222
63223
63224
63225
63226
63227
63228
63229
63230
63231
63232
63233 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
63234 {
63235 private $stderr;
63236
63237
63238
63239
63240
63241
63242 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
63243 {
63244 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
63245
63246 $actualDecorated = $this->isDecorated();
63247 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
63248
63249 if (null === $decorated) {
63250 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
63251 }
63252 }
63253
63254
63255
63256
63257 public function setDecorated($decorated)
63258 {
63259 parent::setDecorated($decorated);
63260 $this->stderr->setDecorated($decorated);
63261 }
63262
63263
63264
63265
63266 public function setFormatter(OutputFormatterInterface $formatter)
63267 {
63268 parent::setFormatter($formatter);
63269 $this->stderr->setFormatter($formatter);
63270 }
63271
63272
63273
63274
63275 public function setVerbosity($level)
63276 {
63277 parent::setVerbosity($level);
63278 $this->stderr->setVerbosity($level);
63279 }
63280
63281
63282
63283
63284 public function getErrorOutput()
63285 {
63286 return $this->stderr;
63287 }
63288
63289
63290
63291
63292 public function setErrorOutput(OutputInterface $error)
63293 {
63294 $this->stderr = $error;
63295 }
63296
63297
63298
63299
63300
63301
63302
63303 protected function hasStdoutSupport()
63304 {
63305 return false === $this->isRunningOS400();
63306 }
63307
63308
63309
63310
63311
63312
63313
63314 protected function hasStderrSupport()
63315 {
63316 return false === $this->isRunningOS400();
63317 }
63318
63319
63320
63321
63322
63323
63324
63325 private function isRunningOS400()
63326 {
63327 $checks = array(
63328 \function_exists('php_uname') ? php_uname('s') : '',
63329 getenv('OSTYPE'),
63330 PHP_OS,
63331 );
63332
63333 return false !== stripos(implode(';', $checks), 'OS400');
63334 }
63335
63336
63337
63338
63339 private function openOutputStream()
63340 {
63341 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
63342
63343 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
63344 }
63345
63346
63347
63348
63349 private function openErrorStream()
63350 {
63351 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
63352
63353 return fopen($errorStream, 'w');
63354 }
63355 }
63356 <?php
63357
63358
63359
63360
63361
63362
63363
63364
63365
63366
63367 namespace Symfony\Component\Console\Output;
63368
63369
63370
63371
63372
63373
63374
63375 interface ConsoleOutputInterface extends OutputInterface
63376 {
63377
63378
63379
63380
63381
63382 public function getErrorOutput();
63383
63384 public function setErrorOutput(OutputInterface $error);
63385 }
63386 <?php
63387
63388
63389
63390
63391
63392
63393
63394
63395
63396
63397 namespace Symfony\Component\Console\Output;
63398
63399 use Symfony\Component\Console\Formatter\OutputFormatter;
63400 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
63401
63402
63403
63404
63405
63406
63407
63408
63409
63410 class NullOutput implements OutputInterface
63411 {
63412
63413
63414
63415 public function setFormatter(OutputFormatterInterface $formatter)
63416 {
63417
63418 }
63419
63420
63421
63422
63423 public function getFormatter()
63424 {
63425
63426 return new OutputFormatter();
63427 }
63428
63429
63430
63431
63432 public function setDecorated($decorated)
63433 {
63434
63435 }
63436
63437
63438
63439
63440 public function isDecorated()
63441 {
63442 return false;
63443 }
63444
63445
63446
63447
63448 public function setVerbosity($level)
63449 {
63450
63451 }
63452
63453
63454
63455
63456 public function getVerbosity()
63457 {
63458 return self::VERBOSITY_QUIET;
63459 }
63460
63461
63462
63463
63464 public function isQuiet()
63465 {
63466 return true;
63467 }
63468
63469
63470
63471
63472 public function isVerbose()
63473 {
63474 return false;
63475 }
63476
63477
63478
63479
63480 public function isVeryVerbose()
63481 {
63482 return false;
63483 }
63484
63485
63486
63487
63488 public function isDebug()
63489 {
63490 return false;
63491 }
63492
63493
63494
63495
63496 public function writeln($messages, $options = self::OUTPUT_NORMAL)
63497 {
63498
63499 }
63500
63501
63502
63503
63504 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
63505 {
63506
63507 }
63508 }
63509 <?php
63510
63511
63512
63513
63514
63515
63516
63517
63518
63519
63520 namespace Symfony\Component\Console\Output;
63521
63522 use Symfony\Component\Console\Formatter\OutputFormatter;
63523 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
63524
63525
63526
63527
63528
63529
63530
63531
63532
63533
63534
63535
63536
63537
63538 abstract class Output implements OutputInterface
63539 {
63540 private $verbosity;
63541 private $formatter;
63542
63543
63544
63545
63546
63547
63548 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
63549 {
63550 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
63551 $this->formatter = $formatter ?: new OutputFormatter();
63552 $this->formatter->setDecorated($decorated);
63553 }
63554
63555
63556
63557
63558 public function setFormatter(OutputFormatterInterface $formatter)
63559 {
63560 $this->formatter = $formatter;
63561 }
63562
63563
63564
63565
63566 public function getFormatter()
63567 {
63568 return $this->formatter;
63569 }
63570
63571
63572
63573
63574 public function setDecorated($decorated)
63575 {
63576 $this->formatter->setDecorated($decorated);
63577 }
63578
63579
63580
63581
63582 public function isDecorated()
63583 {
63584 return $this->formatter->isDecorated();
63585 }
63586
63587
63588
63589
63590 public function setVerbosity($level)
63591 {
63592 $this->verbosity = (int) $level;
63593 }
63594
63595
63596
63597
63598 public function getVerbosity()
63599 {
63600 return $this->verbosity;
63601 }
63602
63603
63604
63605
63606 public function isQuiet()
63607 {
63608 return self::VERBOSITY_QUIET === $this->verbosity;
63609 }
63610
63611
63612
63613
63614 public function isVerbose()
63615 {
63616 return self::VERBOSITY_VERBOSE <= $this->verbosity;
63617 }
63618
63619
63620
63621
63622 public function isVeryVerbose()
63623 {
63624 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
63625 }
63626
63627
63628
63629
63630 public function isDebug()
63631 {
63632 return self::VERBOSITY_DEBUG <= $this->verbosity;
63633 }
63634
63635
63636
63637
63638 public function writeln($messages, $options = self::OUTPUT_NORMAL)
63639 {
63640 $this->write($messages, true, $options);
63641 }
63642
63643
63644
63645
63646 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
63647 {
63648 $messages = (array) $messages;
63649
63650 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
63651 $type = $types & $options ?: self::OUTPUT_NORMAL;
63652
63653 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
63654 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
63655
63656 if ($verbosity > $this->getVerbosity()) {
63657 return;
63658 }
63659
63660 foreach ($messages as $message) {
63661 switch ($type) {
63662 case OutputInterface::OUTPUT_NORMAL:
63663 $message = $this->formatter->format($message);
63664 break;
63665 case OutputInterface::OUTPUT_RAW:
63666 break;
63667 case OutputInterface::OUTPUT_PLAIN:
63668 $message = strip_tags($this->formatter->format($message));
63669 break;
63670 }
63671
63672 $this->doWrite($message, $newline);
63673 }
63674 }
63675
63676
63677
63678
63679
63680
63681
63682 abstract protected function doWrite($message, $newline);
63683 }
63684 <?php
63685
63686
63687
63688
63689
63690
63691
63692
63693
63694
63695 namespace Symfony\Component\Console\Output;
63696
63697 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
63698
63699
63700
63701
63702
63703
63704 interface OutputInterface
63705 {
63706 const VERBOSITY_QUIET = 16;
63707 const VERBOSITY_NORMAL = 32;
63708 const VERBOSITY_VERBOSE = 64;
63709 const VERBOSITY_VERY_VERBOSE = 128;
63710 const VERBOSITY_DEBUG = 256;
63711
63712 const OUTPUT_NORMAL = 1;
63713 const OUTPUT_RAW = 2;
63714 const OUTPUT_PLAIN = 4;
63715
63716
63717
63718
63719
63720
63721
63722
63723 public function write($messages, $newline = false, $options = 0);
63724
63725
63726
63727
63728
63729
63730
63731 public function writeln($messages, $options = 0);
63732
63733
63734
63735
63736
63737
63738 public function setVerbosity($level);
63739
63740
63741
63742
63743
63744
63745 public function getVerbosity();
63746
63747
63748
63749
63750
63751
63752 public function setDecorated($decorated);
63753
63754
63755
63756
63757
63758
63759 public function isDecorated();
63760
63761 public function setFormatter(OutputFormatterInterface $formatter);
63762
63763
63764
63765
63766
63767
63768 public function getFormatter();
63769 }
63770 <?php
63771
63772
63773
63774
63775
63776
63777
63778
63779
63780
63781 namespace Symfony\Component\Console\Output;
63782
63783 use Symfony\Component\Console\Exception\InvalidArgumentException;
63784 use Symfony\Component\Console\Exception\RuntimeException;
63785 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
63786
63787
63788
63789
63790
63791
63792
63793
63794
63795
63796
63797
63798
63799
63800 class StreamOutput extends Output
63801 {
63802 private $stream;
63803
63804
63805
63806
63807
63808
63809
63810
63811
63812 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
63813 {
63814 if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
63815 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
63816 }
63817
63818 $this->stream = $stream;
63819
63820 if (null === $decorated) {
63821 $decorated = $this->hasColorSupport();
63822 }
63823
63824 parent::__construct($verbosity, $decorated, $formatter);
63825 }
63826
63827
63828
63829
63830
63831
63832 public function getStream()
63833 {
63834 return $this->stream;
63835 }
63836
63837
63838
63839
63840 protected function doWrite($message, $newline)
63841 {
63842 if ($newline) {
63843 $message .= PHP_EOL;
63844 }
63845
63846 if (false === @fwrite($this->stream, $message)) {
63847
63848 throw new RuntimeException('Unable to write output.');
63849 }
63850
63851 fflush($this->stream);
63852 }
63853
63854
63855
63856
63857
63858
63859
63860
63861
63862
63863
63864
63865
63866
63867 protected function hasColorSupport()
63868 {
63869 if ('Hyper' === getenv('TERM_PROGRAM')) {
63870 return true;
63871 }
63872
63873 if (\DIRECTORY_SEPARATOR === '\\') {
63874 return (\function_exists('sapi_windows_vt100_support')
63875 && @sapi_windows_vt100_support($this->stream))
63876 || false !== getenv('ANSICON')
63877 || 'ON' === getenv('ConEmuANSI')
63878 || 'xterm' === getenv('TERM');
63879 }
63880
63881 if (\function_exists('stream_isatty')) {
63882 return @stream_isatty($this->stream);
63883 }
63884
63885 if (\function_exists('posix_isatty')) {
63886 return @posix_isatty($this->stream);
63887 }
63888
63889 $stat = @fstat($this->stream);
63890
63891 return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
63892 }
63893 }
63894 <?php
63895
63896
63897
63898
63899
63900
63901
63902
63903
63904
63905 namespace Symfony\Component\Console\Question;
63906
63907 use Symfony\Component\Console\Exception\InvalidArgumentException;
63908
63909
63910
63911
63912
63913
63914 class ChoiceQuestion extends Question
63915 {
63916 private $choices;
63917 private $multiselect = false;
63918 private $prompt = ' > ';
63919 private $errorMessage = 'Value "%s" is invalid';
63920
63921
63922
63923
63924
63925
63926 public function __construct($question, array $choices, $default = null)
63927 {
63928 if (!$choices) {
63929 throw new \LogicException('Choice question must have at least 1 choice available.');
63930 }
63931
63932 parent::__construct($question, $default);
63933
63934 $this->choices = $choices;
63935 $this->setValidator($this->getDefaultValidator());
63936 $this->setAutocompleterValues($choices);
63937 }
63938
63939
63940
63941
63942
63943
63944 public function getChoices()
63945 {
63946 return $this->choices;
63947 }
63948
63949
63950
63951
63952
63953
63954
63955
63956
63957
63958 public function setMultiselect($multiselect)
63959 {
63960 $this->multiselect = $multiselect;
63961 $this->setValidator($this->getDefaultValidator());
63962
63963 return $this;
63964 }
63965
63966
63967
63968
63969
63970
63971 public function isMultiselect()
63972 {
63973 return $this->multiselect;
63974 }
63975
63976
63977
63978
63979
63980
63981 public function getPrompt()
63982 {
63983 return $this->prompt;
63984 }
63985
63986
63987
63988
63989
63990
63991
63992
63993 public function setPrompt($prompt)
63994 {
63995 $this->prompt = $prompt;
63996
63997 return $this;
63998 }
63999
64000
64001
64002
64003
64004
64005
64006
64007
64008
64009 public function setErrorMessage($errorMessage)
64010 {
64011 $this->errorMessage = $errorMessage;
64012 $this->setValidator($this->getDefaultValidator());
64013
64014 return $this;
64015 }
64016
64017
64018
64019
64020
64021
64022 private function getDefaultValidator()
64023 {
64024 $choices = $this->choices;
64025 $errorMessage = $this->errorMessage;
64026 $multiselect = $this->multiselect;
64027 $isAssoc = $this->isAssoc($choices);
64028
64029 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
64030
64031 $selectedChoices = str_replace(' ', '', $selected);
64032
64033 if ($multiselect) {
64034
64035 if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
64036 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
64037 }
64038 $selectedChoices = explode(',', $selectedChoices);
64039 } else {
64040 $selectedChoices = array($selected);
64041 }
64042
64043 $multiselectChoices = array();
64044 foreach ($selectedChoices as $value) {
64045 $results = array();
64046 foreach ($choices as $key => $choice) {
64047 if ($choice === $value) {
64048 $results[] = $key;
64049 }
64050 }
64051
64052 if (\count($results) > 1) {
64053 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
64054 }
64055
64056 $result = array_search($value, $choices);
64057
64058 if (!$isAssoc) {
64059 if (false !== $result) {
64060 $result = $choices[$result];
64061 } elseif (isset($choices[$value])) {
64062 $result = $choices[$value];
64063 }
64064 } elseif (false === $result && isset($choices[$value])) {
64065 $result = $value;
64066 }
64067
64068 if (false === $result) {
64069 throw new InvalidArgumentException(sprintf($errorMessage, $value));
64070 }
64071
64072 $multiselectChoices[] = (string) $result;
64073 }
64074
64075 if ($multiselect) {
64076 return $multiselectChoices;
64077 }
64078
64079 return current($multiselectChoices);
64080 };
64081 }
64082 }
64083 <?php
64084
64085
64086
64087
64088
64089
64090
64091
64092
64093
64094 namespace Symfony\Component\Console\Question;
64095
64096
64097
64098
64099
64100
64101 class ConfirmationQuestion extends Question
64102 {
64103 private $trueAnswerRegex;
64104
64105
64106
64107
64108
64109
64110 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
64111 {
64112 parent::__construct($question, (bool) $default);
64113
64114 $this->trueAnswerRegex = $trueAnswerRegex;
64115 $this->setNormalizer($this->getDefaultNormalizer());
64116 }
64117
64118
64119
64120
64121
64122
64123 private function getDefaultNormalizer()
64124 {
64125 $default = $this->getDefault();
64126 $regex = $this->trueAnswerRegex;
64127
64128 return function ($answer) use ($default, $regex) {
64129 if (\is_bool($answer)) {
64130 return $answer;
64131 }
64132
64133 $answerIsTrue = (bool) preg_match($regex, $answer);
64134 if (false === $default) {
64135 return $answer && $answerIsTrue;
64136 }
64137
64138 return !$answer || $answerIsTrue;
64139 };
64140 }
64141 }
64142 <?php
64143
64144
64145
64146
64147
64148
64149
64150
64151
64152
64153 namespace Symfony\Component\Console\Question;
64154
64155 use Symfony\Component\Console\Exception\InvalidArgumentException;
64156 use Symfony\Component\Console\Exception\LogicException;
64157
64158
64159
64160
64161
64162
64163 class Question
64164 {
64165 private $question;
64166 private $attempts;
64167 private $hidden = false;
64168 private $hiddenFallback = true;
64169 private $autocompleterValues;
64170 private $validator;
64171 private $default;
64172 private $normalizer;
64173
64174
64175
64176
64177
64178 public function __construct($question, $default = null)
64179 {
64180 $this->question = $question;
64181 $this->default = $default;
64182 }
64183
64184
64185
64186
64187
64188
64189 public function getQuestion()
64190 {
64191 return $this->question;
64192 }
64193
64194
64195
64196
64197
64198
64199 public function getDefault()
64200 {
64201 return $this->default;
64202 }
64203
64204
64205
64206
64207
64208
64209 public function isHidden()
64210 {
64211 return $this->hidden;
64212 }
64213
64214
64215
64216
64217
64218
64219
64220
64221
64222
64223 public function setHidden($hidden)
64224 {
64225 if ($this->autocompleterValues) {
64226 throw new LogicException('A hidden question cannot use the autocompleter.');
64227 }
64228
64229 $this->hidden = (bool) $hidden;
64230
64231 return $this;
64232 }
64233
64234
64235
64236
64237
64238
64239 public function isHiddenFallback()
64240 {
64241 return $this->hiddenFallback;
64242 }
64243
64244
64245
64246
64247
64248
64249
64250
64251 public function setHiddenFallback($fallback)
64252 {
64253 $this->hiddenFallback = (bool) $fallback;
64254
64255 return $this;
64256 }
64257
64258
64259
64260
64261
64262
64263 public function getAutocompleterValues()
64264 {
64265 return $this->autocompleterValues;
64266 }
64267
64268
64269
64270
64271
64272
64273
64274
64275
64276
64277
64278 public function setAutocompleterValues($values)
64279 {
64280 if (\is_array($values)) {
64281 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
64282 }
64283
64284 if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) {
64285 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
64286 }
64287
64288 if ($this->hidden) {
64289 throw new LogicException('A hidden question cannot use the autocompleter.');
64290 }
64291
64292 $this->autocompleterValues = $values;
64293
64294 return $this;
64295 }
64296
64297
64298
64299
64300
64301
64302
64303
64304 public function setValidator($validator)
64305 {
64306 $this->validator = $validator;
64307
64308 return $this;
64309 }
64310
64311
64312
64313
64314
64315
64316 public function getValidator()
64317 {
64318 return $this->validator;
64319 }
64320
64321
64322
64323
64324
64325
64326
64327
64328
64329
64330
64331
64332 public function setMaxAttempts($attempts)
64333 {
64334 if (null !== $attempts && $attempts < 1) {
64335 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
64336 }
64337
64338 $this->attempts = $attempts;
64339
64340 return $this;
64341 }
64342
64343
64344
64345
64346
64347
64348
64349
64350 public function getMaxAttempts()
64351 {
64352 return $this->attempts;
64353 }
64354
64355
64356
64357
64358
64359
64360
64361
64362
64363
64364 public function setNormalizer($normalizer)
64365 {
64366 $this->normalizer = $normalizer;
64367
64368 return $this;
64369 }
64370
64371
64372
64373
64374
64375
64376
64377
64378 public function getNormalizer()
64379 {
64380 return $this->normalizer;
64381 }
64382
64383 protected function isAssoc($array)
64384 {
64385 return (bool) \count(array_filter(array_keys($array), 'is_string'));
64386 }
64387 }
64388 <?php
64389
64390
64391
64392
64393
64394
64395
64396
64397
64398
64399 namespace Symfony\Component\Console;
64400
64401 use Symfony\Component\Console\Exception\RuntimeException;
64402 use Symfony\Component\Console\Input\StringInput;
64403 use Symfony\Component\Console\Output\ConsoleOutput;
64404 use Symfony\Component\Process\PhpExecutableFinder;
64405 use Symfony\Component\Process\ProcessBuilder;
64406
64407
64408
64409
64410
64411
64412
64413
64414
64415
64416
64417
64418 class Shell
64419 {
64420 private $application;
64421 private $history;
64422 private $output;
64423 private $hasReadline;
64424 private $processIsolation = false;
64425
64426
64427
64428
64429
64430 public function __construct(Application $application)
64431 {
64432 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
64433
64434 $this->hasReadline = \function_exists('readline');
64435 $this->application = $application;
64436 $this->history = getenv('HOME').'/.history_'.$application->getName();
64437 $this->output = new ConsoleOutput();
64438 }
64439
64440
64441
64442
64443 public function run()
64444 {
64445 $this->application->setAutoExit(false);
64446 $this->application->setCatchExceptions(true);
64447
64448 if ($this->hasReadline) {
64449 readline_read_history($this->history);
64450 readline_completion_function(array($this, 'autocompleter'));
64451 }
64452
64453 $this->output->writeln($this->getHeader());
64454 $php = null;
64455 if ($this->processIsolation) {
64456 $finder = new PhpExecutableFinder();
64457 $php = $finder->find();
64458 $this->output->writeln(<<<'EOF'
64459 <info>Running with process isolation, you should consider this:</info>
64460   * each command is executed as separate process,
64461   * commands don't support interactivity, all params must be passed explicitly,
64462   * commands output is not colorized.
64463
64464 EOF
64465 );
64466 }
64467
64468 while (true) {
64469 $command = $this->readline();
64470
64471 if (false === $command) {
64472 $this->output->writeln("\n");
64473
64474 break;
64475 }
64476
64477 if ($this->hasReadline) {
64478 readline_add_history($command);
64479 readline_write_history($this->history);
64480 }
64481
64482 if ($this->processIsolation) {
64483 $pb = new ProcessBuilder();
64484
64485 $process = $pb
64486 ->add($php)
64487 ->add($_SERVER['argv'][0])
64488 ->add($command)
64489 ->inheritEnvironmentVariables(true)
64490 ->getProcess()
64491 ;
64492
64493 $output = $this->output;
64494 $process->run(function ($type, $data) use ($output) {
64495 $output->writeln($data);
64496 });
64497
64498 $ret = $process->getExitCode();
64499 } else {
64500 $ret = $this->application->run(new StringInput($command), $this->output);
64501 }
64502
64503 if (0 !== $ret) {
64504 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
64505 }
64506 }
64507 }
64508
64509
64510
64511
64512
64513
64514 protected function getHeader()
64515 {
64516 return <<<EOF
64517
64518 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
64519
64520 At the prompt, type <comment>help</comment> for some help,
64521 or <comment>list</comment> to get a list of available commands.
64522
64523 To exit the shell, type <comment>^D</comment>.
64524
64525 EOF;
64526 }
64527
64528
64529
64530
64531
64532
64533 protected function getPrompt()
64534 {
64535
64536 return $this->output->getFormatter()->format($this->application->getName().' > ');
64537 }
64538
64539 protected function getOutput()
64540 {
64541 return $this->output;
64542 }
64543
64544 protected function getApplication()
64545 {
64546 return $this->application;
64547 }
64548
64549
64550
64551
64552
64553
64554
64555
64556 private function autocompleter($text)
64557 {
64558 $info = readline_info();
64559 $text = substr($info['line_buffer'], 0, $info['end']);
64560
64561 if ($info['point'] !== $info['end']) {
64562 return true;
64563 }
64564
64565
64566 if (false === strpos($text, ' ') || !$text) {
64567 return array_keys($this->application->all());
64568 }
64569
64570
64571 try {
64572 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
64573 } catch (\Exception $e) {
64574 return true;
64575 }
64576
64577 $list = array('--help');
64578 foreach ($command->getDefinition()->getOptions() as $option) {
64579 $list[] = '--'.$option->getName();
64580 }
64581
64582 return $list;
64583 }
64584
64585
64586
64587
64588
64589
64590 private function readline()
64591 {
64592 if ($this->hasReadline) {
64593 $line = readline($this->getPrompt());
64594 } else {
64595 $this->output->write($this->getPrompt());
64596 $line = fgets(STDIN, 1024);
64597 $line = (false === $line || '' === $line) ? false : rtrim($line);
64598 }
64599
64600 return $line;
64601 }
64602
64603 public function getProcessIsolation()
64604 {
64605 return $this->processIsolation;
64606 }
64607
64608 public function setProcessIsolation($processIsolation)
64609 {
64610 $this->processIsolation = (bool) $processIsolation;
64611
64612 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
64613 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
64614 }
64615 }
64616 }
64617 <?php
64618
64619
64620
64621
64622
64623
64624
64625
64626
64627
64628 namespace Symfony\Component\Console\Style;
64629
64630 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
64631 use Symfony\Component\Console\Helper\ProgressBar;
64632 use Symfony\Component\Console\Output\OutputInterface;
64633
64634
64635
64636
64637
64638
64639 abstract class OutputStyle implements OutputInterface, StyleInterface
64640 {
64641 private $output;
64642
64643 public function __construct(OutputInterface $output)
64644 {
64645 $this->output = $output;
64646 }
64647
64648
64649
64650
64651 public function newLine($count = 1)
64652 {
64653 $this->output->write(str_repeat(PHP_EOL, $count));
64654 }
64655
64656
64657
64658
64659
64660
64661 public function createProgressBar($max = 0)
64662 {
64663 return new ProgressBar($this->output, $max);
64664 }
64665
64666
64667
64668
64669 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
64670 {
64671 $this->output->write($messages, $newline, $type);
64672 }
64673
64674
64675
64676
64677 public function writeln($messages, $type = self::OUTPUT_NORMAL)
64678 {
64679 $this->output->writeln($messages, $type);
64680 }
64681
64682
64683
64684
64685 public function setVerbosity($level)
64686 {
64687 $this->output->setVerbosity($level);
64688 }
64689
64690
64691
64692
64693 public function getVerbosity()
64694 {
64695 return $this->output->getVerbosity();
64696 }
64697
64698
64699
64700
64701 public function setDecorated($decorated)
64702 {
64703 $this->output->setDecorated($decorated);
64704 }
64705
64706
64707
64708
64709 public function isDecorated()
64710 {
64711 return $this->output->isDecorated();
64712 }
64713
64714
64715
64716
64717 public function setFormatter(OutputFormatterInterface $formatter)
64718 {
64719 $this->output->setFormatter($formatter);
64720 }
64721
64722
64723
64724
64725 public function getFormatter()
64726 {
64727 return $this->output->getFormatter();
64728 }
64729 }
64730 <?php
64731
64732
64733
64734
64735
64736
64737
64738
64739
64740
64741 namespace Symfony\Component\Console\Style;
64742
64743
64744
64745
64746
64747
64748 interface StyleInterface
64749 {
64750
64751
64752
64753
64754
64755 public function title($message);
64756
64757
64758
64759
64760
64761
64762 public function section($message);
64763
64764
64765
64766
64767 public function listing(array $elements);
64768
64769
64770
64771
64772
64773
64774 public function text($message);
64775
64776
64777
64778
64779
64780
64781 public function success($message);
64782
64783
64784
64785
64786
64787
64788 public function error($message);
64789
64790
64791
64792
64793
64794
64795 public function warning($message);
64796
64797
64798
64799
64800
64801
64802 public function note($message);
64803
64804
64805
64806
64807
64808
64809 public function caution($message);
64810
64811
64812
64813
64814 public function table(array $headers, array $rows);
64815
64816
64817
64818
64819
64820
64821
64822
64823
64824
64825 public function ask($question, $default = null, $validator = null);
64826
64827
64828
64829
64830
64831
64832
64833
64834
64835 public function askHidden($question, $validator = null);
64836
64837
64838
64839
64840
64841
64842
64843
64844
64845 public function confirm($question, $default = true);
64846
64847
64848
64849
64850
64851
64852
64853
64854
64855
64856 public function choice($question, array $choices, $default = null);
64857
64858
64859
64860
64861
64862
64863 public function newLine($count = 1);
64864
64865
64866
64867
64868
64869
64870 public function progressStart($max = 0);
64871
64872
64873
64874
64875
64876
64877 public function progressAdvance($step = 1);
64878
64879
64880
64881
64882 public function progressFinish();
64883 }
64884 <?php
64885
64886
64887
64888
64889
64890
64891
64892
64893
64894
64895 namespace Symfony\Component\Console\Style;
64896
64897 use Symfony\Component\Console\Application;
64898 use Symfony\Component\Console\Exception\RuntimeException;
64899 use Symfony\Component\Console\Formatter\OutputFormatter;
64900 use Symfony\Component\Console\Helper\Helper;
64901 use Symfony\Component\Console\Helper\ProgressBar;
64902 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
64903 use Symfony\Component\Console\Helper\Table;
64904 use Symfony\Component\Console\Input\InputInterface;
64905 use Symfony\Component\Console\Output\BufferedOutput;
64906 use Symfony\Component\Console\Output\OutputInterface;
64907 use Symfony\Component\Console\Question\ChoiceQuestion;
64908 use Symfony\Component\Console\Question\ConfirmationQuestion;
64909 use Symfony\Component\Console\Question\Question;
64910
64911
64912
64913
64914
64915
64916 class SymfonyStyle extends OutputStyle
64917 {
64918 const MAX_LINE_LENGTH = 120;
64919
64920 private $input;
64921 private $questionHelper;
64922 private $progressBar;
64923 private $lineLength;
64924 private $bufferedOutput;
64925
64926 public function __construct(InputInterface $input, OutputInterface $output)
64927 {
64928 $this->input = $input;
64929 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
64930
64931 $this->lineLength = min($this->getTerminalWidth() - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
64932
64933 parent::__construct($output);
64934 }
64935
64936
64937
64938
64939
64940
64941
64942
64943
64944
64945 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
64946 {
64947 $messages = \is_array($messages) ? array_values($messages) : array($messages);
64948
64949 $this->autoPrependBlock();
64950 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
64951 $this->newLine();
64952 }
64953
64954
64955
64956
64957 public function title($message)
64958 {
64959 $this->autoPrependBlock();
64960 $this->writeln(array(
64961 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
64962 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
64963 ));
64964 $this->newLine();
64965 }
64966
64967
64968
64969
64970 public function section($message)
64971 {
64972 $this->autoPrependBlock();
64973 $this->writeln(array(
64974 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
64975 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
64976 ));
64977 $this->newLine();
64978 }
64979
64980
64981
64982
64983 public function listing(array $elements)
64984 {
64985 $this->autoPrependText();
64986 $elements = array_map(function ($element) {
64987 return sprintf(' * %s', $element);
64988 }, $elements);
64989
64990 $this->writeln($elements);
64991 $this->newLine();
64992 }
64993
64994
64995
64996
64997 public function text($message)
64998 {
64999 $this->autoPrependText();
65000
65001 $messages = \is_array($message) ? array_values($message) : array($message);
65002 foreach ($messages as $message) {
65003 $this->writeln(sprintf(' %s', $message));
65004 }
65005 }
65006
65007
65008
65009
65010
65011
65012 public function comment($message)
65013 {
65014 $messages = \is_array($message) ? array_values($message) : array($message);
65015
65016 $this->autoPrependBlock();
65017 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
65018 $this->newLine();
65019 }
65020
65021
65022
65023
65024 public function success($message)
65025 {
65026 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
65027 }
65028
65029
65030
65031
65032 public function error($message)
65033 {
65034 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
65035 }
65036
65037
65038
65039
65040 public function warning($message)
65041 {
65042 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
65043 }
65044
65045
65046
65047
65048 public function note($message)
65049 {
65050 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
65051 }
65052
65053
65054
65055
65056 public function caution($message)
65057 {
65058 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
65059 }
65060
65061
65062
65063
65064 public function table(array $headers, array $rows)
65065 {
65066 $style = clone Table::getStyleDefinition('symfony-style-guide');
65067 $style->setCellHeaderFormat('<info>%s</info>');
65068
65069 $table = new Table($this);
65070 $table->setHeaders($headers);
65071 $table->setRows($rows);
65072 $table->setStyle($style);
65073
65074 $table->render();
65075 $this->newLine();
65076 }
65077
65078
65079
65080
65081 public function ask($question, $default = null, $validator = null)
65082 {
65083 $question = new Question($question, $default);
65084 $question->setValidator($validator);
65085
65086 return $this->askQuestion($question);
65087 }
65088
65089
65090
65091
65092 public function askHidden($question, $validator = null)
65093 {
65094 $question = new Question($question);
65095
65096 $question->setHidden(true);
65097 $question->setValidator($validator);
65098
65099 return $this->askQuestion($question);
65100 }
65101
65102
65103
65104
65105 public function confirm($question, $default = true)
65106 {
65107 return $this->askQuestion(new ConfirmationQuestion($question, $default));
65108 }
65109
65110
65111
65112
65113 public function choice($question, array $choices, $default = null)
65114 {
65115 if (null !== $default) {
65116 $values = array_flip($choices);
65117 $default = $values[$default];
65118 }
65119
65120 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
65121 }
65122
65123
65124
65125
65126 public function progressStart($max = 0)
65127 {
65128 $this->progressBar = $this->createProgressBar($max);
65129 $this->progressBar->start();
65130 }
65131
65132
65133
65134
65135 public function progressAdvance($step = 1)
65136 {
65137 $this->getProgressBar()->advance($step);
65138 }
65139
65140
65141
65142
65143 public function progressFinish()
65144 {
65145 $this->getProgressBar()->finish();
65146 $this->newLine(2);
65147 $this->progressBar = null;
65148 }
65149
65150
65151
65152
65153 public function createProgressBar($max = 0)
65154 {
65155 $progressBar = parent::createProgressBar($max);
65156
65157 if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
65158 $progressBar->setEmptyBarCharacter('░'); 
65159 $progressBar->setProgressCharacter('');
65160 $progressBar->setBarCharacter('▓'); 
65161 }
65162
65163 return $progressBar;
65164 }
65165
65166
65167
65168
65169 public function askQuestion(Question $question)
65170 {
65171 if ($this->input->isInteractive()) {
65172 $this->autoPrependBlock();
65173 }
65174
65175 if (!$this->questionHelper) {
65176 $this->questionHelper = new SymfonyQuestionHelper();
65177 }
65178
65179 $answer = $this->questionHelper->ask($this->input, $this, $question);
65180
65181 if ($this->input->isInteractive()) {
65182 $this->newLine();
65183 $this->bufferedOutput->write("\n");
65184 }
65185
65186 return $answer;
65187 }
65188
65189
65190
65191
65192 public function writeln($messages, $type = self::OUTPUT_NORMAL)
65193 {
65194 parent::writeln($messages, $type);
65195 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
65196 }
65197
65198
65199
65200
65201 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
65202 {
65203 parent::write($messages, $newline, $type);
65204 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
65205 }
65206
65207
65208
65209
65210 public function newLine($count = 1)
65211 {
65212 parent::newLine($count);
65213 $this->bufferedOutput->write(str_repeat("\n", $count));
65214 }
65215
65216
65217
65218
65219 private function getProgressBar()
65220 {
65221 if (!$this->progressBar) {
65222 throw new RuntimeException('The ProgressBar is not started.');
65223 }
65224
65225 return $this->progressBar;
65226 }
65227
65228 private function getTerminalWidth()
65229 {
65230 $application = new Application();
65231 $dimensions = $application->getTerminalDimensions();
65232
65233 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
65234 }
65235
65236 private function autoPrependBlock()
65237 {
65238 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
65239
65240 if (!isset($chars[0])) {
65241 return $this->newLine(); 
65242 }
65243
65244 $this->newLine(2 - substr_count($chars, "\n"));
65245 }
65246
65247 private function autoPrependText()
65248 {
65249 $fetched = $this->bufferedOutput->fetch();
65250
65251 if ("\n" !== substr($fetched, -1)) {
65252 $this->newLine();
65253 }
65254 }
65255
65256 private function reduceBuffer($messages)
65257 {
65258
65259
65260 return array_map(function ($value) {
65261 return substr($value, -4);
65262 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
65263 }
65264
65265 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
65266 {
65267 $indentLength = 0;
65268 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
65269 $lines = array();
65270
65271 if (null !== $type) {
65272 $type = sprintf('[%s] ', $type);
65273 $indentLength = \strlen($type);
65274 $lineIndentation = str_repeat(' ', $indentLength);
65275 }
65276
65277
65278 foreach ($messages as $key => $message) {
65279 if ($escape) {
65280 $message = OutputFormatter::escape($message);
65281 }
65282
65283 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
65284
65285 if (\count($messages) > 1 && $key < \count($messages) - 1) {
65286 $lines[] = '';
65287 }
65288 }
65289
65290 $firstLineIndex = 0;
65291 if ($padding && $this->isDecorated()) {
65292 $firstLineIndex = 1;
65293 array_unshift($lines, '');
65294 $lines[] = '';
65295 }
65296
65297 foreach ($lines as $i => &$line) {
65298 if (null !== $type) {
65299 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
65300 }
65301
65302 $line = $prefix.$line;
65303 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
65304
65305 if ($style) {
65306 $line = sprintf('<%s>%s</>', $style, $line);
65307 }
65308 }
65309
65310 return $lines;
65311 }
65312 }
65313 <?php
65314
65315
65316
65317
65318
65319
65320
65321
65322
65323
65324 namespace Symfony\Component\Console\Tester;
65325
65326 use Symfony\Component\Console\Application;
65327 use Symfony\Component\Console\Input\ArrayInput;
65328 use Symfony\Component\Console\Input\InputInterface;
65329 use Symfony\Component\Console\Output\OutputInterface;
65330 use Symfony\Component\Console\Output\StreamOutput;
65331
65332
65333
65334
65335
65336
65337
65338
65339
65340
65341
65342 class ApplicationTester
65343 {
65344 private $application;
65345 private $input;
65346 private $output;
65347 private $statusCode;
65348
65349 public function __construct(Application $application)
65350 {
65351 $this->application = $application;
65352 }
65353
65354
65355
65356
65357
65358
65359
65360
65361
65362
65363
65364
65365
65366
65367
65368 public function run(array $input, $options = array())
65369 {
65370 $this->input = new ArrayInput($input);
65371 if (isset($options['interactive'])) {
65372 $this->input->setInteractive($options['interactive']);
65373 }
65374
65375 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
65376 if (isset($options['decorated'])) {
65377 $this->output->setDecorated($options['decorated']);
65378 }
65379 if (isset($options['verbosity'])) {
65380 $this->output->setVerbosity($options['verbosity']);
65381 }
65382
65383 return $this->statusCode = $this->application->run($this->input, $this->output);
65384 }
65385
65386
65387
65388
65389
65390
65391
65392
65393 public function getDisplay($normalize = false)
65394 {
65395 rewind($this->output->getStream());
65396
65397 $display = stream_get_contents($this->output->getStream());
65398
65399 if ($normalize) {
65400 $display = str_replace(PHP_EOL, "\n", $display);
65401 }
65402
65403 return $display;
65404 }
65405
65406
65407
65408
65409
65410
65411 public function getInput()
65412 {
65413 return $this->input;
65414 }
65415
65416
65417
65418
65419
65420
65421 public function getOutput()
65422 {
65423 return $this->output;
65424 }
65425
65426
65427
65428
65429
65430
65431 public function getStatusCode()
65432 {
65433 return $this->statusCode;
65434 }
65435 }
65436 <?php
65437
65438
65439
65440
65441
65442
65443
65444
65445
65446
65447 namespace Symfony\Component\Console\Tester;
65448
65449 use Symfony\Component\Console\Command\Command;
65450 use Symfony\Component\Console\Input\ArrayInput;
65451 use Symfony\Component\Console\Input\InputInterface;
65452 use Symfony\Component\Console\Output\OutputInterface;
65453 use Symfony\Component\Console\Output\StreamOutput;
65454
65455
65456
65457
65458
65459
65460 class CommandTester
65461 {
65462 private $command;
65463 private $input;
65464 private $output;
65465 private $statusCode;
65466
65467 public function __construct(Command $command)
65468 {
65469 $this->command = $command;
65470 }
65471
65472
65473
65474
65475
65476
65477
65478
65479
65480
65481
65482
65483
65484
65485
65486 public function execute(array $input, array $options = array())
65487 {
65488
65489
65490 if (!isset($input['command'])
65491 && (null !== $application = $this->command->getApplication())
65492 && $application->getDefinition()->hasArgument('command')
65493 ) {
65494 $input = array_merge(array('command' => $this->command->getName()), $input);
65495 }
65496
65497 $this->input = new ArrayInput($input);
65498 if (isset($options['interactive'])) {
65499 $this->input->setInteractive($options['interactive']);
65500 }
65501
65502 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
65503 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
65504 if (isset($options['verbosity'])) {
65505 $this->output->setVerbosity($options['verbosity']);
65506 }
65507
65508 return $this->statusCode = $this->command->run($this->input, $this->output);
65509 }
65510
65511
65512
65513
65514
65515
65516
65517
65518 public function getDisplay($normalize = false)
65519 {
65520 rewind($this->output->getStream());
65521
65522 $display = stream_get_contents($this->output->getStream());
65523
65524 if ($normalize) {
65525 $display = str_replace(PHP_EOL, "\n", $display);
65526 }
65527
65528 return $display;
65529 }
65530
65531
65532
65533
65534
65535
65536 public function getInput()
65537 {
65538 return $this->input;
65539 }
65540
65541
65542
65543
65544
65545
65546 public function getOutput()
65547 {
65548 return $this->output;
65549 }
65550
65551
65552
65553
65554
65555
65556 public function getStatusCode()
65557 {
65558 return $this->statusCode;
65559 }
65560 }
65561 <?php
65562
65563
65564
65565
65566
65567
65568
65569
65570
65571
65572 namespace Symfony\Component\Debug;
65573
65574 use Psr\Log\AbstractLogger;
65575
65576
65577
65578
65579
65580
65581 class BufferingLogger extends AbstractLogger
65582 {
65583 private $logs = array();
65584
65585 public function log($level, $message, array $context = array())
65586 {
65587 $this->logs[] = array($level, $message, $context);
65588 }
65589
65590 public function cleanLogs()
65591 {
65592 $logs = $this->logs;
65593 $this->logs = array();
65594
65595 return $logs;
65596 }
65597 }
65598 <?php
65599
65600
65601
65602
65603
65604
65605
65606
65607
65608
65609 namespace Symfony\Component\Debug;
65610
65611
65612
65613
65614
65615
65616 class Debug
65617 {
65618 private static $enabled = false;
65619
65620
65621
65622
65623
65624
65625
65626
65627
65628 public static function enable($errorReportingLevel = null, $displayErrors = true)
65629 {
65630 if (static::$enabled) {
65631 return;
65632 }
65633
65634 static::$enabled = true;
65635
65636 if (null !== $errorReportingLevel) {
65637 error_reporting($errorReportingLevel);
65638 } else {
65639 error_reporting(-1);
65640 }
65641
65642 if (!\in_array(\PHP_SAPI, array('cli', 'phpdbg'), true)) {
65643 ini_set('display_errors', 0);
65644 ExceptionHandler::register();
65645 } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) {
65646
65647 ini_set('display_errors', 1);
65648 }
65649 if ($displayErrors) {
65650 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
65651 } else {
65652 ErrorHandler::register()->throwAt(0, true);
65653 }
65654
65655 DebugClassLoader::enable();
65656 }
65657 }
65658 <?php
65659
65660
65661
65662
65663
65664
65665
65666
65667
65668
65669 namespace Symfony\Component\Debug;
65670
65671
65672
65673
65674
65675
65676
65677
65678
65679
65680
65681
65682 class DebugClassLoader
65683 {
65684 private $classLoader;
65685 private $isFinder;
65686 private $loaded = array();
65687 private $wasFinder;
65688 private static $caseCheck;
65689 private static $deprecated = array();
65690 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
65691 private static $darwinCache = array('/' => array('/', array()));
65692
65693
65694
65695
65696 public function __construct($classLoader)
65697 {
65698 $this->wasFinder = \is_object($classLoader) && method_exists($classLoader, 'findFile');
65699
65700 if ($this->wasFinder) {
65701 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
65702 $this->classLoader = array($classLoader, 'loadClass');
65703 $this->isFinder = true;
65704 } else {
65705 $this->classLoader = $classLoader;
65706 $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
65707 }
65708
65709 if (!isset(self::$caseCheck)) {
65710 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
65711 $i = strrpos($file, \DIRECTORY_SEPARATOR);
65712 $dir = substr($file, 0, 1 + $i);
65713 $file = substr($file, 1 + $i);
65714 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
65715 $test = realpath($dir.$test);
65716
65717 if (false === $test || false === $i) {
65718
65719 self::$caseCheck = 0;
65720 } elseif (substr($test, -\strlen($file)) === $file) {
65721
65722 self::$caseCheck = 1;
65723 } elseif (false !== stripos(PHP_OS, 'darwin')) {
65724
65725 self::$caseCheck = 2;
65726 } else {
65727
65728 self::$caseCheck = 0;
65729 }
65730 }
65731 }
65732
65733
65734
65735
65736
65737
65738 public function getClassLoader()
65739 {
65740 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
65741 }
65742
65743
65744
65745
65746 public static function enable()
65747 {
65748
65749 class_exists('Symfony\Component\Debug\ErrorHandler');
65750 class_exists('Psr\Log\LogLevel');
65751
65752 if (!\is_array($functions = spl_autoload_functions())) {
65753 return;
65754 }
65755
65756 foreach ($functions as $function) {
65757 spl_autoload_unregister($function);
65758 }
65759
65760 foreach ($functions as $function) {
65761 if (!\is_array($function) || !$function[0] instanceof self) {
65762 $function = array(new static($function), 'loadClass');
65763 }
65764
65765 spl_autoload_register($function);
65766 }
65767 }
65768
65769
65770
65771
65772 public static function disable()
65773 {
65774 if (!\is_array($functions = spl_autoload_functions())) {
65775 return;
65776 }
65777
65778 foreach ($functions as $function) {
65779 spl_autoload_unregister($function);
65780 }
65781
65782 foreach ($functions as $function) {
65783 if (\is_array($function) && $function[0] instanceof self) {
65784 $function = $function[0]->getClassLoader();
65785 }
65786
65787 spl_autoload_register($function);
65788 }
65789 }
65790
65791
65792
65793
65794
65795
65796
65797
65798
65799
65800 public function findFile($class)
65801 {
65802 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
65803
65804 if ($this->wasFinder) {
65805 return $this->classLoader[0]->findFile($class);
65806 }
65807 }
65808
65809
65810
65811
65812
65813
65814
65815
65816
65817
65818 public function loadClass($class)
65819 {
65820 ErrorHandler::stackErrors();
65821
65822 try {
65823 if ($this->isFinder && !isset($this->loaded[$class])) {
65824 $this->loaded[$class] = true;
65825 if ($file = $this->classLoader[0]->findFile($class)) {
65826 require $file;
65827 }
65828 } else {
65829 \call_user_func($this->classLoader, $class);
65830 $file = false;
65831 }
65832 } catch (\Exception $e) {
65833 ErrorHandler::unstackErrors();
65834
65835 throw $e;
65836 } catch (\Throwable $e) {
65837 ErrorHandler::unstackErrors();
65838
65839 throw $e;
65840 }
65841
65842 ErrorHandler::unstackErrors();
65843
65844 $exists = class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
65845
65846 if ($class && '\\' === $class[0]) {
65847 $class = substr($class, 1);
65848 }
65849
65850 if ($exists) {
65851 $refl = new \ReflectionClass($class);
65852 $name = $refl->getName();
65853
65854 if ($name !== $class && 0 === strcasecmp($name, $class)) {
65855 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
65856 }
65857
65858 if (\in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
65859 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
65860 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
65861 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
65862 } else {
65863 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
65864 $len = 0;
65865 $ns = '';
65866 } else {
65867 $ns = substr($name, 0, $len);
65868 }
65869 $parent = get_parent_class($class);
65870
65871 if (!$parent || strncmp($ns, $parent, $len)) {
65872 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
65873 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
65874 }
65875
65876 $parentInterfaces = array();
65877 $deprecatedInterfaces = array();
65878 if ($parent) {
65879 foreach (class_implements($parent) as $interface) {
65880 $parentInterfaces[$interface] = 1;
65881 }
65882 }
65883
65884 foreach ($refl->getInterfaceNames() as $interface) {
65885 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
65886 $deprecatedInterfaces[] = $interface;
65887 }
65888 foreach (class_implements($interface) as $interface) {
65889 $parentInterfaces[$interface] = 1;
65890 }
65891 }
65892
65893 foreach ($deprecatedInterfaces as $interface) {
65894 if (!isset($parentInterfaces[$interface])) {
65895 @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);
65896 }
65897 }
65898 }
65899 }
65900 }
65901
65902 if ($file) {
65903 if (!$exists) {
65904 if (false !== strpos($class, '/')) {
65905 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));
65906 }
65907
65908 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));
65909 }
65910 if (self::$caseCheck) {
65911 $real = explode('\\', $class.strrchr($file, '.'));
65912 $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
65913
65914 $i = \count($tail) - 1;
65915 $j = \count($real) - 1;
65916
65917 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
65918 --$i;
65919 --$j;
65920 }
65921
65922 array_splice($tail, 0, $i + 1);
65923 }
65924 if (self::$caseCheck && $tail) {
65925 $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
65926 $tailLen = \strlen($tail);
65927 $real = $refl->getFileName();
65928
65929 if (2 === self::$caseCheck) {
65930
65931
65932 $i = 1 + strrpos($real, '/');
65933 $file = substr($real, $i);
65934 $real = substr($real, 0, $i);
65935
65936 if (isset(self::$darwinCache[$real])) {
65937 $kDir = $real;
65938 } else {
65939 $kDir = strtolower($real);
65940
65941 if (isset(self::$darwinCache[$kDir])) {
65942 $real = self::$darwinCache[$kDir][0];
65943 } else {
65944 $dir = getcwd();
65945 chdir($real);
65946 $real = getcwd().'/';
65947 chdir($dir);
65948
65949 $dir = $real;
65950 $k = $kDir;
65951 $i = \strlen($dir) - 1;
65952 while (!isset(self::$darwinCache[$k])) {
65953 self::$darwinCache[$k] = array($dir, array());
65954 self::$darwinCache[$dir] = &self::$darwinCache[$k];
65955
65956 while ('/' !== $dir[--$i]) {
65957 }
65958 $k = substr($k, 0, ++$i);
65959 $dir = substr($dir, 0, $i--);
65960 }
65961 }
65962 }
65963
65964 $dirFiles = self::$darwinCache[$kDir][1];
65965
65966 if (isset($dirFiles[$file])) {
65967 $kFile = $file;
65968 } else {
65969 $kFile = strtolower($file);
65970
65971 if (!isset($dirFiles[$kFile])) {
65972 foreach (scandir($real, 2) as $f) {
65973 if ('.' !== $f[0]) {
65974 $dirFiles[$f] = $f;
65975 if ($f === $file) {
65976 $kFile = $k = $file;
65977 } elseif ($f !== $k = strtolower($f)) {
65978 $dirFiles[$k] = $f;
65979 }
65980 }
65981 }
65982 self::$darwinCache[$kDir][1] = $dirFiles;
65983 }
65984 }
65985
65986 $real .= $dirFiles[$kFile];
65987 }
65988
65989 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
65990 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
65991 ) {
65992 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)));
65993 }
65994 }
65995
65996 return true;
65997 }
65998 }
65999 }
66000 <?php
66001
66002
66003
66004
66005
66006
66007
66008
66009
66010
66011 namespace Symfony\Component\Debug;
66012
66013 use Psr\Log\LoggerInterface;
66014 use Psr\Log\LogLevel;
66015 use Symfony\Component\Debug\Exception\ContextErrorException;
66016 use Symfony\Component\Debug\Exception\FatalErrorException;
66017 use Symfony\Component\Debug\Exception\FatalThrowableError;
66018 use Symfony\Component\Debug\Exception\OutOfMemoryException;
66019 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
66020 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
66021 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
66022 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
66023
66024
66025
66026
66027
66028
66029
66030
66031
66032
66033
66034
66035
66036
66037
66038
66039
66040
66041
66042
66043
66044
66045
66046 class ErrorHandler
66047 {
66048
66049
66050
66051 const TYPE_DEPRECATION = -100;
66052
66053 private $levels = array(
66054 E_DEPRECATED => 'Deprecated',
66055 E_USER_DEPRECATED => 'User Deprecated',
66056 E_NOTICE => 'Notice',
66057 E_USER_NOTICE => 'User Notice',
66058 E_STRICT => 'Runtime Notice',
66059 E_WARNING => 'Warning',
66060 E_USER_WARNING => 'User Warning',
66061 E_COMPILE_WARNING => 'Compile Warning',
66062 E_CORE_WARNING => 'Core Warning',
66063 E_USER_ERROR => 'User Error',
66064 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
66065 E_COMPILE_ERROR => 'Compile Error',
66066 E_PARSE => 'Parse Error',
66067 E_ERROR => 'Error',
66068 E_CORE_ERROR => 'Core Error',
66069 );
66070
66071 private $loggers = array(
66072 E_DEPRECATED => array(null, LogLevel::INFO),
66073 E_USER_DEPRECATED => array(null, LogLevel::INFO),
66074 E_NOTICE => array(null, LogLevel::WARNING),
66075 E_USER_NOTICE => array(null, LogLevel::WARNING),
66076 E_STRICT => array(null, LogLevel::WARNING),
66077 E_WARNING => array(null, LogLevel::WARNING),
66078 E_USER_WARNING => array(null, LogLevel::WARNING),
66079 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
66080 E_CORE_WARNING => array(null, LogLevel::WARNING),
66081 E_USER_ERROR => array(null, LogLevel::CRITICAL),
66082 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
66083 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
66084 E_PARSE => array(null, LogLevel::CRITICAL),
66085 E_ERROR => array(null, LogLevel::CRITICAL),
66086 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
66087 );
66088
66089 private $thrownErrors = 0x1FFF; 
66090 private $scopedErrors = 0x1FFF; 
66091 private $tracedErrors = 0x77FB; 
66092 private $screamedErrors = 0x55; 
66093 private $loggedErrors = 0;
66094
66095 private $loggedTraces = array();
66096 private $isRecursive = 0;
66097 private $isRoot = false;
66098 private $exceptionHandler;
66099 private $bootstrappingLogger;
66100
66101 private static $reservedMemory;
66102 private static $stackedErrors = array();
66103 private static $stackedErrorLevels = array();
66104 private static $toStringException = null;
66105 private static $exitCode = 0;
66106
66107
66108
66109
66110
66111
66112 private $displayErrors = 0x1FFF;
66113
66114
66115
66116
66117
66118
66119
66120
66121
66122 public static function register($handler = null, $replace = true)
66123 {
66124 if (null === self::$reservedMemory) {
66125 self::$reservedMemory = str_repeat('x', 10240);
66126 register_shutdown_function(__CLASS__.'::handleFatalError');
66127 }
66128
66129 $levels = -1;
66130
66131 if ($handlerIsNew = !$handler instanceof self) {
66132
66133 if (null !== $handler) {
66134 $levels = $replace ? $handler : 0;
66135 $replace = true;
66136 }
66137 $handler = new static();
66138 }
66139
66140 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
66141 restore_error_handler();
66142
66143 set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
66144 $handler->isRoot = true;
66145 }
66146
66147 if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) {
66148 $handler = $prev[0];
66149 $replace = false;
66150 }
66151 if (!$replace && $prev) {
66152 restore_error_handler();
66153 $handlerIsRegistered = \is_array($prev) && $handler === $prev[0];
66154 } else {
66155 $handlerIsRegistered = true;
66156 }
66157 if (\is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
66158 restore_exception_handler();
66159 if (!$handlerIsRegistered) {
66160 $handler = $prev[0];
66161 } elseif ($handler !== $prev[0] && $replace) {
66162 set_exception_handler(array($handler, 'handleException'));
66163 $p = $prev[0]->setExceptionHandler(null);
66164 $handler->setExceptionHandler($p);
66165 $prev[0]->setExceptionHandler($p);
66166 }
66167 } else {
66168 $handler->setExceptionHandler($prev);
66169 }
66170
66171 $handler->throwAt($levels & $handler->thrownErrors, true);
66172
66173 return $handler;
66174 }
66175
66176 public function __construct(BufferingLogger $bootstrappingLogger = null)
66177 {
66178 if ($bootstrappingLogger) {
66179 $this->bootstrappingLogger = $bootstrappingLogger;
66180 $this->setDefaultLogger($bootstrappingLogger);
66181 }
66182 }
66183
66184
66185
66186
66187
66188
66189
66190
66191 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
66192 {
66193 $loggers = array();
66194
66195 if (\is_array($levels)) {
66196 foreach ($levels as $type => $logLevel) {
66197 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
66198 $loggers[$type] = array($logger, $logLevel);
66199 }
66200 }
66201 } else {
66202 if (null === $levels) {
66203 $levels = E_ALL | E_STRICT;
66204 }
66205 foreach ($this->loggers as $type => $log) {
66206 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
66207 $log[0] = $logger;
66208 $loggers[$type] = $log;
66209 }
66210 }
66211 }
66212
66213 $this->setLoggers($loggers);
66214 }
66215
66216
66217
66218
66219
66220
66221
66222
66223
66224
66225 public function setLoggers(array $loggers)
66226 {
66227 $prevLogged = $this->loggedErrors;
66228 $prev = $this->loggers;
66229 $flush = array();
66230
66231 foreach ($loggers as $type => $log) {
66232 if (!isset($prev[$type])) {
66233 throw new \InvalidArgumentException('Unknown error type: '.$type);
66234 }
66235 if (!\is_array($log)) {
66236 $log = array($log);
66237 } elseif (!array_key_exists(0, $log)) {
66238 throw new \InvalidArgumentException('No logger provided');
66239 }
66240 if (null === $log[0]) {
66241 $this->loggedErrors &= ~$type;
66242 } elseif ($log[0] instanceof LoggerInterface) {
66243 $this->loggedErrors |= $type;
66244 } else {
66245 throw new \InvalidArgumentException('Invalid logger provided');
66246 }
66247 $this->loggers[$type] = $log + $prev[$type];
66248
66249 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
66250 $flush[$type] = $type;
66251 }
66252 }
66253 $this->reRegister($prevLogged | $this->thrownErrors);
66254
66255 if ($flush) {
66256 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
66257 $type = $log[2]['type'];
66258 if (!isset($flush[$type])) {
66259 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
66260 } elseif ($this->loggers[$type][0]) {
66261 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
66262 }
66263 }
66264 }
66265
66266 return $prev;
66267 }
66268
66269
66270
66271
66272
66273
66274
66275
66276
66277
66278 public function setExceptionHandler($handler)
66279 {
66280 if (null !== $handler && !\is_callable($handler)) {
66281 throw new \LogicException('The exception handler must be a valid PHP callable.');
66282 }
66283 $prev = $this->exceptionHandler;
66284 $this->exceptionHandler = $handler;
66285
66286 return $prev;
66287 }
66288
66289
66290
66291
66292
66293
66294
66295
66296
66297 public function throwAt($levels, $replace = false)
66298 {
66299 $prev = $this->thrownErrors;
66300 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
66301 if (!$replace) {
66302 $this->thrownErrors |= $prev;
66303 }
66304 $this->reRegister($prev | $this->loggedErrors);
66305
66306
66307 $this->displayErrors = $this->thrownErrors;
66308
66309 return $prev;
66310 }
66311
66312
66313
66314
66315
66316
66317
66318
66319
66320 public function scopeAt($levels, $replace = false)
66321 {
66322 $prev = $this->scopedErrors;
66323 $this->scopedErrors = (int) $levels;
66324 if (!$replace) {
66325 $this->scopedErrors |= $prev;
66326 }
66327
66328 return $prev;
66329 }
66330
66331
66332
66333
66334
66335
66336
66337
66338
66339 public function traceAt($levels, $replace = false)
66340 {
66341 $prev = $this->tracedErrors;
66342 $this->tracedErrors = (int) $levels;
66343 if (!$replace) {
66344 $this->tracedErrors |= $prev;
66345 }
66346
66347 return $prev;
66348 }
66349
66350
66351
66352
66353
66354
66355
66356
66357
66358 public function screamAt($levels, $replace = false)
66359 {
66360 $prev = $this->screamedErrors;
66361 $this->screamedErrors = (int) $levels;
66362 if (!$replace) {
66363 $this->screamedErrors |= $prev;
66364 }
66365
66366 return $prev;
66367 }
66368
66369
66370
66371
66372 private function reRegister($prev)
66373 {
66374 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
66375 $handler = set_error_handler('var_dump');
66376 $handler = \is_array($handler) ? $handler[0] : null;
66377 restore_error_handler();
66378 if ($handler === $this) {
66379 restore_error_handler();
66380 if ($this->isRoot) {
66381 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
66382 } else {
66383 set_error_handler(array($this, 'handleError'));
66384 }
66385 }
66386 }
66387 }
66388
66389
66390
66391
66392
66393
66394
66395
66396
66397
66398
66399
66400
66401
66402
66403 public function handleError($type, $message, $file, $line)
66404 {
66405 $level = error_reporting();
66406 $silenced = 0 === ($level & $type);
66407 $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
66408 $log = $this->loggedErrors & $type;
66409 $throw = $this->thrownErrors & $type & $level;
66410 $type &= $level | $this->screamedErrors;
66411
66412 if (!$type || (!$log && !$throw)) {
66413 return !$silenced && $type && $log;
66414 }
66415 $scope = $this->scopedErrors & $type;
66416
66417 if (4 < $numArgs = \func_num_args()) {
66418 $context = $scope ? (func_get_arg(4) ?: array()) : array();
66419 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
66420 } else {
66421 $context = array();
66422 $backtrace = null;
66423 }
66424
66425 if (isset($context['GLOBALS']) && $scope) {
66426 $e = $context; 
66427 unset($e['GLOBALS'], $context); 
66428 $context = $e;
66429 }
66430
66431 if (null !== $backtrace && $type & E_ERROR) {
66432
66433
66434
66435 $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
66436
66437 return true;
66438 }
66439
66440 if ($throw) {
66441 if (null !== self::$toStringException) {
66442 $throw = self::$toStringException;
66443 self::$toStringException = null;
66444 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
66445
66446 $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
66447 } else {
66448 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
66449 }
66450
66451 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
66452
66453
66454
66455
66456 $throw->errorHandlerCanary = new ErrorHandlerCanary();
66457 }
66458
66459 if (E_USER_ERROR & $type) {
66460 $backtrace = $backtrace ?: $throw->getTrace();
66461
66462 for ($i = 1; isset($backtrace[$i]); ++$i) {
66463 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
66464 && '__toString' === $backtrace[$i]['function']
66465 && '->' === $backtrace[$i]['type']
66466 && !isset($backtrace[$i - 1]['class'])
66467 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
66468 ) {
66469
66470
66471
66472
66473
66474
66475
66476 foreach ($context as $e) {
66477 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
66478 if (1 === $i) {
66479
66480 $throw = $e;
66481 break;
66482 }
66483 self::$toStringException = $e;
66484
66485 return true;
66486 }
66487 }
66488
66489 if (1 < $i) {
66490
66491 $this->handleException($throw);
66492
66493
66494 return false;
66495 }
66496 }
66497 }
66498 }
66499
66500 throw $throw;
66501 }
66502
66503
66504 $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
66505 $trace = true;
66506
66507 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
66508 $trace = false;
66509 } else {
66510 $this->loggedTraces[$e] = 1;
66511 }
66512
66513 $e = compact('type', 'file', 'line', 'level');
66514
66515 if ($type & $level) {
66516 if ($scope) {
66517 $e['scope_vars'] = $context;
66518 if ($trace) {
66519 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
66520 }
66521 } elseif ($trace) {
66522 if (null === $backtrace) {
66523 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
66524 } else {
66525 foreach ($backtrace as &$frame) {
66526 unset($frame['args'], $frame);
66527 }
66528 $e['stack'] = $backtrace;
66529 }
66530 }
66531 }
66532
66533 if ($this->isRecursive) {
66534 $log = 0;
66535 } elseif (self::$stackedErrorLevels) {
66536 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
66537 } else {
66538 try {
66539 $this->isRecursive = true;
66540 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
66541 $this->isRecursive = false;
66542 } catch (\Exception $e) {
66543 $this->isRecursive = false;
66544
66545 throw $e;
66546 } catch (\Throwable $e) {
66547 $this->isRecursive = false;
66548
66549 throw $e;
66550 }
66551 }
66552
66553 return !$silenced && $type && $log;
66554 }
66555
66556
66557
66558
66559
66560
66561
66562
66563
66564 public function handleException($exception, array $error = null)
66565 {
66566 if (null === $error) {
66567 self::$exitCode = 255;
66568 }
66569 if (!$exception instanceof \Exception) {
66570 $exception = new FatalThrowableError($exception);
66571 }
66572 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
66573 $handlerException = null;
66574
66575 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
66576 $e = array(
66577 'type' => $type,
66578 'file' => $exception->getFile(),
66579 'line' => $exception->getLine(),
66580 'level' => error_reporting(),
66581 'stack' => $exception->getTrace(),
66582 );
66583 if ($exception instanceof FatalErrorException) {
66584 if ($exception instanceof FatalThrowableError) {
66585 $error = array(
66586 'type' => $type,
66587 'message' => $message = $exception->getMessage(),
66588 'file' => $e['file'],
66589 'line' => $e['line'],
66590 );
66591 } else {
66592 $message = 'Fatal '.$exception->getMessage();
66593 }
66594 } elseif ($exception instanceof \ErrorException) {
66595 $message = 'Uncaught '.$exception->getMessage();
66596 if ($exception instanceof ContextErrorException) {
66597 $e['context'] = $exception->getContext();
66598 }
66599 } else {
66600 $message = 'Uncaught Exception: '.$exception->getMessage();
66601 }
66602 }
66603 if ($this->loggedErrors & $type) {
66604 try {
66605 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
66606 } catch (\Exception $handlerException) {
66607 } catch (\Throwable $handlerException) {
66608 }
66609 }
66610 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
66611 foreach ($this->getFatalErrorHandlers() as $handler) {
66612 if ($e = $handler->handleError($error, $exception)) {
66613 $exception = $e;
66614 break;
66615 }
66616 }
66617 }
66618 $exceptionHandler = $this->exceptionHandler;
66619 $this->exceptionHandler = null;
66620 try {
66621 if (null !== $exceptionHandler) {
66622 return \call_user_func($exceptionHandler, $exception);
66623 }
66624 $handlerException = $handlerException ?: $exception;
66625 } catch (\Exception $handlerException) {
66626 } catch (\Throwable $handlerException) {
66627 }
66628 if ($exception === $handlerException) {
66629 self::$reservedMemory = null; 
66630 throw $exception; 
66631 }
66632 $this->handleException($handlerException);
66633 }
66634
66635
66636
66637
66638
66639
66640
66641
66642 public static function handleFatalError(array $error = null)
66643 {
66644 if (null === self::$reservedMemory) {
66645 return;
66646 }
66647
66648 $handler = self::$reservedMemory = null;
66649 $handlers = array();
66650 $previousHandler = null;
66651 $sameHandlerLimit = 10;
66652
66653 while (!\is_array($handler) || !$handler[0] instanceof self) {
66654 $handler = set_exception_handler('var_dump');
66655 restore_exception_handler();
66656
66657 if (!$handler) {
66658 break;
66659 }
66660 restore_exception_handler();
66661
66662 if ($handler !== $previousHandler) {
66663 array_unshift($handlers, $handler);
66664 $previousHandler = $handler;
66665 } elseif (0 === --$sameHandlerLimit) {
66666 $handler = null;
66667 break;
66668 }
66669 }
66670 foreach ($handlers as $h) {
66671 set_exception_handler($h);
66672 }
66673 if (!$handler) {
66674 return;
66675 }
66676 if ($handler !== $h) {
66677 $handler[0]->setExceptionHandler($h);
66678 }
66679 $handler = $handler[0];
66680 $handlers = array();
66681
66682 if ($exit = null === $error) {
66683 $error = error_get_last();
66684 }
66685
66686 try {
66687 while (self::$stackedErrorLevels) {
66688 static::unstackErrors();
66689 }
66690 } catch (\Exception $exception) {
66691
66692 } catch (\Throwable $exception) {
66693
66694 }
66695
66696 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
66697
66698 $handler->throwAt(0, true);
66699 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
66700
66701 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
66702 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
66703 } else {
66704 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
66705 }
66706 }
66707
66708 try {
66709 if (isset($exception)) {
66710 self::$exitCode = 255;
66711 $handler->handleException($exception, $error);
66712 }
66713 } catch (FatalErrorException $e) {
66714
66715 }
66716
66717 if ($exit && self::$exitCode) {
66718 $exitCode = self::$exitCode;
66719 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
66720 }
66721 }
66722
66723
66724
66725
66726
66727
66728
66729
66730
66731
66732
66733
66734 public static function stackErrors()
66735 {
66736 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
66737 }
66738
66739
66740
66741
66742 public static function unstackErrors()
66743 {
66744 $level = array_pop(self::$stackedErrorLevels);
66745
66746 if (null !== $level) {
66747 $e = error_reporting($level);
66748 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
66749
66750 error_reporting($e);
66751 }
66752 }
66753
66754 if (empty(self::$stackedErrorLevels)) {
66755 $errors = self::$stackedErrors;
66756 self::$stackedErrors = array();
66757
66758 foreach ($errors as $e) {
66759 $e[0]->log($e[1], $e[2], $e[3]);
66760 }
66761 }
66762 }
66763
66764
66765
66766
66767
66768
66769
66770
66771 protected function getFatalErrorHandlers()
66772 {
66773 return array(
66774 new UndefinedFunctionFatalErrorHandler(),
66775 new UndefinedMethodFatalErrorHandler(),
66776 new ClassNotFoundFatalErrorHandler(),
66777 );
66778 }
66779
66780
66781
66782
66783
66784
66785
66786
66787 public function setLevel($level)
66788 {
66789 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
66790
66791 $level = null === $level ? error_reporting() : $level;
66792 $this->throwAt($level, true);
66793 }
66794
66795
66796
66797
66798
66799
66800
66801
66802 public function setDisplayErrors($displayErrors)
66803 {
66804 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
66805
66806 if ($displayErrors) {
66807 $this->throwAt($this->displayErrors, true);
66808 } else {
66809 $displayErrors = $this->displayErrors;
66810 $this->throwAt(0, true);
66811 $this->displayErrors = $displayErrors;
66812 }
66813 }
66814
66815
66816
66817
66818
66819
66820
66821
66822
66823 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
66824 {
66825 @trigger_error('The '.__METHOD__.' static method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the setLoggers() or setDefaultLogger() methods instead.', E_USER_DEPRECATED);
66826
66827 $handler = set_error_handler('var_dump');
66828 $handler = \is_array($handler) ? $handler[0] : null;
66829 restore_error_handler();
66830 if (!$handler instanceof self) {
66831 return;
66832 }
66833 if ('deprecation' === $channel) {
66834 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
66835 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
66836 } elseif ('scream' === $channel) {
66837 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
66838 $handler->screamAt(E_ALL | E_STRICT);
66839 } elseif ('emergency' === $channel) {
66840 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
66841 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
66842 }
66843 }
66844
66845
66846
66847
66848 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
66849 {
66850 $this->handleError(E_USER_DEPRECATED, 'The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the handleError() method instead.', __FILE__, __LINE__, array());
66851
66852 return $this->handleError($level, $message, $file, $line, (array) $context);
66853 }
66854
66855
66856
66857
66858
66859
66860 public function handleFatal()
66861 {
66862 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the handleFatalError() method instead.', E_USER_DEPRECATED);
66863
66864 static::handleFatalError();
66865 }
66866 }
66867
66868
66869
66870
66871
66872
66873
66874
66875 class ErrorHandlerCanary
66876 {
66877 private static $displayErrors = null;
66878
66879 public function __construct()
66880 {
66881 if (null === self::$displayErrors) {
66882 self::$displayErrors = ini_set('display_errors', 1);
66883 }
66884 }
66885
66886 public function __destruct()
66887 {
66888 if (null !== self::$displayErrors) {
66889 ini_set('display_errors', self::$displayErrors);
66890 self::$displayErrors = null;
66891 }
66892 }
66893 }
66894 <?php
66895
66896
66897
66898
66899
66900
66901
66902
66903
66904
66905 namespace Symfony\Component\Debug\Exception;
66906
66907
66908
66909
66910
66911
66912 class ClassNotFoundException extends FatalErrorException
66913 {
66914 public function __construct($message, \ErrorException $previous)
66915 {
66916 parent::__construct(
66917 $message,
66918 $previous->getCode(),
66919 $previous->getSeverity(),
66920 $previous->getFile(),
66921 $previous->getLine(),
66922 null,
66923 true,
66924 null,
66925 $previous->getPrevious()
66926 );
66927 $this->setTrace($previous->getTrace());
66928 }
66929 }
66930 <?php
66931
66932
66933
66934
66935
66936
66937
66938
66939
66940
66941 namespace Symfony\Component\Debug\Exception;
66942
66943
66944
66945
66946
66947
66948 class ContextErrorException extends \ErrorException
66949 {
66950 private $context = array();
66951
66952 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
66953 {
66954 parent::__construct($message, $code, $severity, $filename, $lineno);
66955 $this->context = $context;
66956 }
66957
66958
66959
66960
66961 public function getContext()
66962 {
66963 return $this->context;
66964 }
66965 }
66966 <?php
66967
66968
66969
66970
66971
66972
66973
66974
66975
66976
66977 namespace Symfony\Component\Debug\Exception;
66978
66979 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
66980
66981
66982
66983
66984
66985
66986 class DummyException extends \ErrorException
66987 {
66988 }
66989 <?php
66990
66991
66992
66993
66994
66995
66996
66997
66998
66999
67000 namespace Symfony\Component\HttpKernel\Exception;
67001
67002
67003
67004
67005
67006
67007
67008
67009
67010
67011 class FatalErrorException extends \ErrorException
67012 {
67013 }
67014
67015 namespace Symfony\Component\Debug\Exception;
67016
67017 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
67018
67019
67020
67021
67022
67023
67024 class FatalErrorException extends LegacyFatalErrorException
67025 {
67026 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null, $previous = null)
67027 {
67028 parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
67029
67030 if (null !== $trace) {
67031 if (!$traceArgs) {
67032 foreach ($trace as &$frame) {
67033 unset($frame['args'], $frame['this'], $frame);
67034 }
67035 }
67036
67037 $this->setTrace($trace);
67038 } elseif (null !== $traceOffset) {
67039 if (\function_exists('xdebug_get_function_stack')) {
67040 $trace = xdebug_get_function_stack();
67041 if (0 < $traceOffset) {
67042 array_splice($trace, -$traceOffset);
67043 }
67044
67045 foreach ($trace as &$frame) {
67046 if (!isset($frame['type'])) {
67047
67048 if (isset($frame['class'])) {
67049 $frame['type'] = '::';
67050 }
67051 } elseif ('dynamic' === $frame['type']) {
67052 $frame['type'] = '->';
67053 } elseif ('static' === $frame['type']) {
67054 $frame['type'] = '::';
67055 }
67056
67057
67058 if (!$traceArgs) {
67059 unset($frame['params'], $frame['args']);
67060 } elseif (isset($frame['params']) && !isset($frame['args'])) {
67061 $frame['args'] = $frame['params'];
67062 unset($frame['params']);
67063 }
67064 }
67065
67066 unset($frame);
67067 $trace = array_reverse($trace);
67068 } elseif (\function_exists('symfony_debug_backtrace')) {
67069 $trace = symfony_debug_backtrace();
67070 if (0 < $traceOffset) {
67071 array_splice($trace, 0, $traceOffset);
67072 }
67073 } else {
67074 $trace = array();
67075 }
67076
67077 $this->setTrace($trace);
67078 }
67079 }
67080
67081 protected function setTrace($trace)
67082 {
67083 $traceReflector = new \ReflectionProperty('Exception', 'trace');
67084 $traceReflector->setAccessible(true);
67085 $traceReflector->setValue($this, $trace);
67086 }
67087 }
67088 <?php
67089
67090
67091
67092
67093
67094
67095
67096
67097
67098
67099 namespace Symfony\Component\Debug\Exception;
67100
67101
67102
67103
67104
67105
67106 class FatalThrowableError extends FatalErrorException
67107 {
67108 public function __construct(\Throwable $e)
67109 {
67110 if ($e instanceof \ParseError) {
67111 $message = 'Parse error: '.$e->getMessage();
67112 $severity = E_PARSE;
67113 } elseif ($e instanceof \TypeError) {
67114 $message = 'Type error: '.$e->getMessage();
67115 $severity = E_RECOVERABLE_ERROR;
67116 } else {
67117 $message = $e->getMessage();
67118 $severity = E_ERROR;
67119 }
67120
67121 \ErrorException::__construct(
67122 $message,
67123 $e->getCode(),
67124 $severity,
67125 $e->getFile(),
67126 $e->getLine(),
67127 $e->getPrevious()
67128 );
67129
67130 $this->setTrace($e->getTrace());
67131 }
67132 }
67133 <?php
67134
67135
67136
67137
67138
67139
67140
67141
67142
67143
67144 namespace Symfony\Component\HttpKernel\Exception;
67145
67146 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
67147
67148
67149
67150
67151
67152
67153
67154
67155
67156
67157 class FlattenException
67158 {
67159 private $handler;
67160
67161 public static function __callStatic($method, $args)
67162 {
67163 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
67164 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_called_class(), $method));
67165 }
67166
67167 return \call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
67168 }
67169
67170 public function __call($method, $args)
67171 {
67172 if (!isset($this->handler)) {
67173 $this->handler = new DebugFlattenException();
67174 }
67175
67176 if (!method_exists($this->handler, $method)) {
67177 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_class($this), $method));
67178 }
67179
67180 return \call_user_func_array(array($this->handler, $method), $args);
67181 }
67182 }
67183
67184 namespace Symfony\Component\Debug\Exception;
67185
67186 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
67187 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
67188
67189
67190
67191
67192
67193
67194
67195
67196 class FlattenException extends LegacyFlattenException
67197 {
67198 private $message;
67199 private $code;
67200 private $previous;
67201 private $trace;
67202 private $class;
67203 private $statusCode;
67204 private $headers;
67205 private $file;
67206 private $line;
67207
67208 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
67209 {
67210 $e = new static();
67211 $e->setMessage($exception->getMessage());
67212 $e->setCode($exception->getCode());
67213
67214 if ($exception instanceof HttpExceptionInterface) {
67215 $statusCode = $exception->getStatusCode();
67216 $headers = array_merge($headers, $exception->getHeaders());
67217 }
67218
67219 if (null === $statusCode) {
67220 $statusCode = 500;
67221 }
67222
67223 $e->setStatusCode($statusCode);
67224 $e->setHeaders($headers);
67225 $e->setTraceFromException($exception);
67226 $e->setClass(\get_class($exception));
67227 $e->setFile($exception->getFile());
67228 $e->setLine($exception->getLine());
67229
67230 $previous = $exception->getPrevious();
67231
67232 if ($previous instanceof \Exception) {
67233 $e->setPrevious(static::create($previous));
67234 } elseif ($previous instanceof \Throwable) {
67235 $e->setPrevious(static::create(new FatalThrowableError($previous)));
67236 }
67237
67238 return $e;
67239 }
67240
67241 public function toArray()
67242 {
67243 $exceptions = array();
67244 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
67245 $exceptions[] = array(
67246 'message' => $exception->getMessage(),
67247 'class' => $exception->getClass(),
67248 'trace' => $exception->getTrace(),
67249 );
67250 }
67251
67252 return $exceptions;
67253 }
67254
67255 public function getStatusCode()
67256 {
67257 return $this->statusCode;
67258 }
67259
67260 public function setStatusCode($code)
67261 {
67262 $this->statusCode = $code;
67263 }
67264
67265 public function getHeaders()
67266 {
67267 return $this->headers;
67268 }
67269
67270 public function setHeaders(array $headers)
67271 {
67272 $this->headers = $headers;
67273 }
67274
67275 public function getClass()
67276 {
67277 return $this->class;
67278 }
67279
67280 public function setClass($class)
67281 {
67282 $this->class = $class;
67283 }
67284
67285 public function getFile()
67286 {
67287 return $this->file;
67288 }
67289
67290 public function setFile($file)
67291 {
67292 $this->file = $file;
67293 }
67294
67295 public function getLine()
67296 {
67297 return $this->line;
67298 }
67299
67300 public function setLine($line)
67301 {
67302 $this->line = $line;
67303 }
67304
67305 public function getMessage()
67306 {
67307 return $this->message;
67308 }
67309
67310 public function setMessage($message)
67311 {
67312 $this->message = $message;
67313 }
67314
67315 public function getCode()
67316 {
67317 return $this->code;
67318 }
67319
67320 public function setCode($code)
67321 {
67322 $this->code = $code;
67323 }
67324
67325 public function getPrevious()
67326 {
67327 return $this->previous;
67328 }
67329
67330 public function setPrevious(FlattenException $previous)
67331 {
67332 $this->previous = $previous;
67333 }
67334
67335 public function getAllPrevious()
67336 {
67337 $exceptions = array();
67338 $e = $this;
67339 while ($e = $e->getPrevious()) {
67340 $exceptions[] = $e;
67341 }
67342
67343 return $exceptions;
67344 }
67345
67346 public function getTrace()
67347 {
67348 return $this->trace;
67349 }
67350
67351 public function setTraceFromException(\Exception $exception)
67352 {
67353 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
67354 }
67355
67356 public function setTrace($trace, $file, $line)
67357 {
67358 $this->trace = array();
67359 $this->trace[] = array(
67360 'namespace' => '',
67361 'short_class' => '',
67362 'class' => '',
67363 'type' => '',
67364 'function' => '',
67365 'file' => $file,
67366 'line' => $line,
67367 'args' => array(),
67368 );
67369 foreach ($trace as $entry) {
67370 $class = '';
67371 $namespace = '';
67372 if (isset($entry['class'])) {
67373 $parts = explode('\\', $entry['class']);
67374 $class = array_pop($parts);
67375 $namespace = implode('\\', $parts);
67376 }
67377
67378 $this->trace[] = array(
67379 'namespace' => $namespace,
67380 'short_class' => $class,
67381 'class' => isset($entry['class']) ? $entry['class'] : '',
67382 'type' => isset($entry['type']) ? $entry['type'] : '',
67383 'function' => isset($entry['function']) ? $entry['function'] : null,
67384 'file' => isset($entry['file']) ? $entry['file'] : null,
67385 'line' => isset($entry['line']) ? $entry['line'] : null,
67386 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
67387 );
67388 }
67389 }
67390
67391 private function flattenArgs($args, $level = 0, &$count = 0)
67392 {
67393 $result = array();
67394 foreach ($args as $key => $value) {
67395 if (++$count > 1e4) {
67396 return array('array', '*SKIPPED over 10000 entries*');
67397 }
67398 if ($value instanceof \__PHP_Incomplete_Class) {
67399
67400 $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
67401 } elseif (\is_object($value)) {
67402 $result[$key] = array('object', \get_class($value));
67403 } elseif (\is_array($value)) {
67404 if ($level > 10) {
67405 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
67406 } else {
67407 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
67408 }
67409 } elseif (null === $value) {
67410 $result[$key] = array('null', null);
67411 } elseif (\is_bool($value)) {
67412 $result[$key] = array('boolean', $value);
67413 } elseif (\is_resource($value)) {
67414 $result[$key] = array('resource', get_resource_type($value));
67415 } else {
67416 $result[$key] = array('string', (string) $value);
67417 }
67418 }
67419
67420 return $result;
67421 }
67422
67423 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
67424 {
67425 $array = new \ArrayObject($value);
67426
67427 return $array['__PHP_Incomplete_Class_Name'];
67428 }
67429 }
67430 <?php
67431
67432
67433
67434
67435
67436
67437
67438
67439
67440
67441 namespace Symfony\Component\Debug\Exception;
67442
67443
67444
67445
67446
67447
67448 class OutOfMemoryException extends FatalErrorException
67449 {
67450 }
67451 <?php
67452
67453
67454
67455
67456
67457
67458
67459
67460
67461
67462 namespace Symfony\Component\Debug\Exception;
67463
67464
67465
67466
67467
67468
67469 class UndefinedFunctionException extends FatalErrorException
67470 {
67471 public function __construct($message, \ErrorException $previous)
67472 {
67473 parent::__construct(
67474 $message,
67475 $previous->getCode(),
67476 $previous->getSeverity(),
67477 $previous->getFile(),
67478 $previous->getLine(),
67479 null,
67480 true,
67481 null,
67482 $previous->getPrevious()
67483 );
67484 $this->setTrace($previous->getTrace());
67485 }
67486 }
67487 <?php
67488
67489
67490
67491
67492
67493
67494
67495
67496
67497
67498 namespace Symfony\Component\Debug\Exception;
67499
67500
67501
67502
67503
67504
67505 class UndefinedMethodException extends FatalErrorException
67506 {
67507 public function __construct($message, \ErrorException $previous)
67508 {
67509 parent::__construct(
67510 $message,
67511 $previous->getCode(),
67512 $previous->getSeverity(),
67513 $previous->getFile(),
67514 $previous->getLine(),
67515 null,
67516 true,
67517 null,
67518 $previous->getPrevious()
67519 );
67520 $this->setTrace($previous->getTrace());
67521 }
67522 }
67523 <?php
67524
67525
67526
67527
67528
67529
67530
67531
67532
67533
67534 namespace Symfony\Component\Debug;
67535
67536 use Symfony\Component\Debug\Exception\FlattenException;
67537 use Symfony\Component\Debug\Exception\OutOfMemoryException;
67538 use Symfony\Component\HttpFoundation\Response;
67539
67540
67541
67542
67543
67544
67545
67546
67547
67548
67549
67550
67551
67552 class ExceptionHandler
67553 {
67554 private $debug;
67555 private $charset;
67556 private $handler;
67557 private $caughtBuffer;
67558 private $caughtLength;
67559 private $fileLinkFormat;
67560
67561 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
67562 {
67563 if (false !== strpos($charset, '%')) {
67564 @trigger_error('Providing $fileLinkFormat as second argument to '.__METHOD__.' is deprecated since Symfony 2.8 and will be unsupported in 3.0. Please provide it as third argument, after $charset.', E_USER_DEPRECATED);
67565
67566
67567 $pivot = $fileLinkFormat;
67568 $fileLinkFormat = $charset;
67569 $charset = $pivot;
67570 }
67571 $this->debug = $debug;
67572 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
67573 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
67574 }
67575
67576
67577
67578
67579
67580
67581
67582
67583
67584
67585 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
67586 {
67587 $handler = new static($debug, $charset, $fileLinkFormat);
67588
67589 $prev = set_exception_handler(array($handler, 'handle'));
67590 if (\is_array($prev) && $prev[0] instanceof ErrorHandler) {
67591 restore_exception_handler();
67592 $prev[0]->setExceptionHandler(array($handler, 'handle'));
67593 }
67594
67595 return $handler;
67596 }
67597
67598
67599
67600
67601
67602
67603
67604
67605 public function setHandler($handler)
67606 {
67607 if (null !== $handler && !\is_callable($handler)) {
67608 throw new \LogicException('The exception handler must be a valid PHP callable.');
67609 }
67610 $old = $this->handler;
67611 $this->handler = $handler;
67612
67613 return $old;
67614 }
67615
67616
67617
67618
67619
67620
67621
67622
67623 public function setFileLinkFormat($format)
67624 {
67625 $old = $this->fileLinkFormat;
67626 $this->fileLinkFormat = $format;
67627
67628 return $old;
67629 }
67630
67631
67632
67633
67634
67635
67636
67637
67638
67639 public function handle(\Exception $exception)
67640 {
67641 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
67642 $this->failSafeHandle($exception);
67643
67644 return;
67645 }
67646
67647 $caughtLength = $this->caughtLength = 0;
67648
67649 ob_start(array($this, 'catchOutput'));
67650 $this->failSafeHandle($exception);
67651 while (null === $this->caughtBuffer && ob_end_flush()) {
67652
67653 }
67654 if (isset($this->caughtBuffer[0])) {
67655 ob_start(array($this, 'cleanOutput'));
67656 echo $this->caughtBuffer;
67657 $caughtLength = ob_get_length();
67658 }
67659 $this->caughtBuffer = null;
67660
67661 try {
67662 \call_user_func($this->handler, $exception);
67663 $this->caughtLength = $caughtLength;
67664 } catch (\Exception $e) {
67665 if (!$caughtLength) {
67666
67667 throw $exception;
67668 }
67669 }
67670 }
67671
67672
67673
67674
67675
67676
67677
67678
67679 private function failSafeHandle(\Exception $exception)
67680 {
67681 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
67682 && __CLASS__ !== \get_class($this)
67683 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
67684 && __CLASS__ !== $reflector->class
67685 ) {
67686 $response = $this->createResponse($exception);
67687 $response->sendHeaders();
67688 $response->sendContent();
67689 @trigger_error(sprintf("The %s::createResponse method is deprecated since Symfony 2.8 and won't be called anymore when handling an exception in 3.0.", $reflector->class), E_USER_DEPRECATED);
67690
67691 return;
67692 }
67693
67694 $this->sendPhpResponse($exception);
67695 }
67696
67697
67698
67699
67700
67701
67702
67703
67704
67705 public function sendPhpResponse($exception)
67706 {
67707 if (!$exception instanceof FlattenException) {
67708 $exception = FlattenException::create($exception);
67709 }
67710
67711 if (!headers_sent()) {
67712 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
67713 foreach ($exception->getHeaders() as $name => $value) {
67714 header($name.': '.$value, false);
67715 }
67716 header('Content-Type: text/html; charset='.$this->charset);
67717 }
67718
67719 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
67720 }
67721
67722
67723
67724
67725
67726
67727
67728
67729
67730
67731 public function createResponse($exception)
67732 {
67733 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67734
67735 if (!$exception instanceof FlattenException) {
67736 $exception = FlattenException::create($exception);
67737 }
67738
67739 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
67740 }
67741
67742
67743
67744
67745
67746
67747
67748
67749 public function getHtml($exception)
67750 {
67751 if (!$exception instanceof FlattenException) {
67752 $exception = FlattenException::create($exception);
67753 }
67754
67755 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
67756 }
67757
67758
67759
67760
67761
67762
67763 public function getContent(FlattenException $exception)
67764 {
67765 switch ($exception->getStatusCode()) {
67766 case 404:
67767 $title = 'Sorry, the page you are looking for could not be found.';
67768 break;
67769 default:
67770 $title = 'Whoops, looks like something went wrong.';
67771 }
67772
67773 $content = '';
67774 if ($this->debug) {
67775 try {
67776 $count = \count($exception->getAllPrevious());
67777 $total = $count + 1;
67778 foreach ($exception->toArray() as $position => $e) {
67779 $ind = $count - $position + 1;
67780 $class = $this->formatClass($e['class']);
67781 $message = nl2br($this->escapeHtml($e['message']));
67782 $content .= sprintf(<<<'EOF'
67783                         <h2 class="block_exception clear_fix">
67784                             <span class="exception_counter">%d/%d</span>
67785                             <span class="exception_title">%s%s:</span>
67786                             <span class="exception_message">%s</span>
67787                         </h2>
67788                         <div class="block">
67789                             <ol class="traces list_exception">
67790
67791 EOF
67792 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
67793 foreach ($e['trace'] as $trace) {
67794 $content .= '       <li>';
67795 if ($trace['function']) {
67796 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
67797 }
67798 if (isset($trace['file']) && isset($trace['line'])) {
67799 $content .= $this->formatPath($trace['file'], $trace['line']);
67800 }
67801 $content .= "</li>\n";
67802 }
67803
67804 $content .= "    </ol>\n</div>\n";
67805 }
67806 } catch (\Exception $e) {
67807
67808 if ($this->debug) {
67809 $title = sprintf('Exception thrown when handling an exception (%s: %s)', \get_class($e), $this->escapeHtml($e->getMessage()));
67810 } else {
67811 $title = 'Whoops, looks like something went wrong.';
67812 }
67813 }
67814 }
67815
67816 return <<<EOF
67817             <div id="sf-resetcontent" class="sf-reset">
67818                 <h1>$title</h1>
67819                 $content
67820             </div>
67821 EOF;
67822 }
67823
67824
67825
67826
67827
67828
67829 public function getStylesheet(FlattenException $exception)
67830 {
67831 return <<<'EOF'
67832             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
67833             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
67834             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
67835             .sf-reset .clear_fix { display:inline-block; }
67836             .sf-reset * html .clear_fix { height:1%; }
67837             .sf-reset .clear_fix { display:block; }
67838             .sf-reset, .sf-reset .block { margin: auto }
67839             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
67840             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
67841             .sf-reset strong { font-weight:bold; }
67842             .sf-reset a { color:#6c6159; cursor: default; }
67843             .sf-reset a img { border:none; }
67844             .sf-reset a:hover { text-decoration:underline; }
67845             .sf-reset em { font-style:italic; }
67846             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
67847             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
67848             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
67849             .sf-reset .exception_message { margin-left: 3em; display: block; }
67850             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
67851             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
67852                 -webkit-border-bottom-right-radius: 16px;
67853                 -webkit-border-bottom-left-radius: 16px;
67854                 -moz-border-radius-bottomright: 16px;
67855                 -moz-border-radius-bottomleft: 16px;
67856                 border-bottom-right-radius: 16px;
67857                 border-bottom-left-radius: 16px;
67858                 border-bottom:1px solid #ccc;
67859                 border-right:1px solid #ccc;
67860                 border-left:1px solid #ccc;
67861                 word-wrap: break-word;
67862             }
67863             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
67864                 -webkit-border-top-left-radius: 16px;
67865                 -webkit-border-top-right-radius: 16px;
67866                 -moz-border-radius-topleft: 16px;
67867                 -moz-border-radius-topright: 16px;
67868                 border-top-left-radius: 16px;
67869                 border-top-right-radius: 16px;
67870                 border-top:1px solid #ccc;
67871                 border-right:1px solid #ccc;
67872                 border-left:1px solid #ccc;
67873                 overflow: hidden;
67874                 word-wrap: break-word;
67875             }
67876             .sf-reset a { background:none; color:#868686; text-decoration:none; }
67877             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
67878             .sf-reset ol { padding: 10px 0; }
67879             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
67880                 -webkit-border-radius: 10px;
67881                 -moz-border-radius: 10px;
67882                 border-radius: 10px;
67883                 border: 1px solid #ccc;
67884             }
67885 EOF;
67886 }
67887
67888 private function decorate($content, $css)
67889 {
67890 return <<<EOF
67891 <!DOCTYPE html>
67892 <html>
67893     <head>
67894         <meta charset="{$this->charset}" />
67895         <meta name="robots" content="noindex,nofollow" />
67896         <style>
67897             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
67898             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;}
67899
67900             html { background: #eee; padding: 10px }
67901             img { border: 0; }
67902             #sf-resetcontent { width:970px; margin:0 auto; }
67903             $css
67904         </style>
67905     </head>
67906     <body>
67907         $content
67908     </body>
67909 </html>
67910 EOF;
67911 }
67912
67913 private function formatClass($class)
67914 {
67915 $parts = explode('\\', $class);
67916
67917 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
67918 }
67919
67920 private function formatPath($path, $line)
67921 {
67922 $path = $this->escapeHtml($path);
67923 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
67924
67925 if ($linkFormat = $this->fileLinkFormat) {
67926 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
67927
67928 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
67929 }
67930
67931 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);
67932 }
67933
67934
67935
67936
67937
67938
67939
67940
67941 private function formatArgs(array $args)
67942 {
67943 $result = array();
67944 foreach ($args as $key => $item) {
67945 if ('object' === $item[0]) {
67946 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
67947 } elseif ('array' === $item[0]) {
67948 $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
67949 } elseif ('string' === $item[0]) {
67950 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
67951 } elseif ('null' === $item[0]) {
67952 $formattedValue = '<em>null</em>';
67953 } elseif ('boolean' === $item[0]) {
67954 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
67955 } elseif ('resource' === $item[0]) {
67956 $formattedValue = '<em>resource</em>';
67957 } else {
67958 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
67959 }
67960
67961 $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
67962 }
67963
67964 return implode(', ', $result);
67965 }
67966
67967
67968
67969
67970
67971
67972 protected static function utf8Htmlize($str)
67973 {
67974 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
67975
67976 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
67977 }
67978
67979
67980
67981
67982 private function escapeHtml($str)
67983 {
67984 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
67985 }
67986
67987
67988
67989
67990 public function catchOutput($buffer)
67991 {
67992 $this->caughtBuffer = $buffer;
67993
67994 return '';
67995 }
67996
67997
67998
67999
68000 public function cleanOutput($buffer)
68001 {
68002 if ($this->caughtLength) {
68003
68004 $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
68005 if (isset($cleanBuffer[0])) {
68006 $buffer = $cleanBuffer;
68007 }
68008 }
68009
68010 return $buffer;
68011 }
68012 }
68013 <?php
68014
68015
68016
68017
68018
68019
68020
68021
68022
68023
68024 namespace Symfony\Component\Debug\FatalErrorHandler;
68025
68026 use Composer\Autoload\ClassLoader as ComposerClassLoader;
68027 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
68028 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
68029 use Symfony\Component\Debug\DebugClassLoader;
68030 use Symfony\Component\Debug\Exception\ClassNotFoundException;
68031 use Symfony\Component\Debug\Exception\FatalErrorException;
68032
68033
68034
68035
68036
68037
68038 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
68039 {
68040
68041
68042
68043 public function handleError(array $error, FatalErrorException $exception)
68044 {
68045 $messageLen = \strlen($error['message']);
68046 $notFoundSuffix = '\' not found';
68047 $notFoundSuffixLen = \strlen($notFoundSuffix);
68048 if ($notFoundSuffixLen > $messageLen) {
68049 return;
68050 }
68051
68052 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
68053 return;
68054 }
68055
68056 foreach (array('class', 'interface', 'trait') as $typeName) {
68057 $prefix = ucfirst($typeName).' \'';
68058 $prefixLen = \strlen($prefix);
68059 if (0 !== strpos($error['message'], $prefix)) {
68060 continue;
68061 }
68062
68063 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
68064 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
68065 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
68066 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
68067 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
68068 $tail = ' for another namespace?';
68069 } else {
68070 $className = $fullyQualifiedClassName;
68071 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
68072 $tail = '?';
68073 }
68074
68075 if ($candidates = $this->getClassCandidates($className)) {
68076 $tail = array_pop($candidates).'"?';
68077 if ($candidates) {
68078 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
68079 } else {
68080 $tail = ' for "'.$tail;
68081 }
68082 }
68083 $message .= "\nDid you forget a \"use\" statement".$tail;
68084
68085 return new ClassNotFoundException($message, $exception);
68086 }
68087 }
68088
68089
68090
68091
68092
68093
68094
68095
68096
68097
68098
68099 private function getClassCandidates($class)
68100 {
68101 if (!\is_array($functions = spl_autoload_functions())) {
68102 return array();
68103 }
68104
68105
68106 $classes = array();
68107
68108 foreach ($functions as $function) {
68109 if (!\is_array($function)) {
68110 continue;
68111 }
68112
68113 if ($function[0] instanceof DebugClassLoader) {
68114 $function = $function[0]->getClassLoader();
68115
68116
68117 if (\is_object($function)) {
68118 $function = array($function);
68119 }
68120
68121 if (!\is_array($function)) {
68122 continue;
68123 }
68124 }
68125
68126 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
68127 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
68128 foreach ($paths as $path) {
68129 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
68130 }
68131 }
68132 }
68133 if ($function[0] instanceof ComposerClassLoader) {
68134 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
68135 foreach ($paths as $path) {
68136 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
68137 }
68138 }
68139 }
68140 }
68141
68142 return array_unique($classes);
68143 }
68144
68145
68146
68147
68148
68149
68150
68151
68152 private function findClassInPath($path, $class, $prefix)
68153 {
68154 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
68155 return array();
68156 }
68157
68158 $classes = array();
68159 $filename = $class.'.php';
68160 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
68161 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
68162 $classes[] = $class;
68163 }
68164 }
68165
68166 return $classes;
68167 }
68168
68169
68170
68171
68172
68173
68174
68175
68176 private function convertFileToClass($path, $file, $prefix)
68177 {
68178 $candidates = array(
68179
68180 $namespacedClass = str_replace(array($path.\DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
68181
68182 $prefix.$namespacedClass,
68183
68184 $prefix.'\\'.$namespacedClass,
68185
68186 str_replace('\\', '_', $namespacedClass),
68187
68188 str_replace('\\', '_', $prefix.$namespacedClass),
68189
68190 str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
68191 );
68192
68193 if ($prefix) {
68194 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
68195 }
68196
68197
68198
68199
68200 foreach ($candidates as $candidate) {
68201 if ($this->classExists($candidate)) {
68202 return $candidate;
68203 }
68204 }
68205
68206 require_once $file;
68207
68208 foreach ($candidates as $candidate) {
68209 if ($this->classExists($candidate)) {
68210 return $candidate;
68211 }
68212 }
68213 }
68214
68215
68216
68217
68218
68219
68220 private function classExists($class)
68221 {
68222 return class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
68223 }
68224 }
68225 <?php
68226
68227
68228
68229
68230
68231
68232
68233
68234
68235
68236 namespace Symfony\Component\Debug\FatalErrorHandler;
68237
68238 use Symfony\Component\Debug\Exception\FatalErrorException;
68239
68240
68241
68242
68243
68244
68245 interface FatalErrorHandlerInterface
68246 {
68247
68248
68249
68250
68251
68252
68253
68254
68255 public function handleError(array $error, FatalErrorException $exception);
68256 }
68257 <?php
68258
68259
68260
68261
68262
68263
68264
68265
68266
68267
68268 namespace Symfony\Component\Debug\FatalErrorHandler;
68269
68270 use Symfony\Component\Debug\Exception\FatalErrorException;
68271 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
68272
68273
68274
68275
68276
68277
68278 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
68279 {
68280
68281
68282
68283 public function handleError(array $error, FatalErrorException $exception)
68284 {
68285 $messageLen = \strlen($error['message']);
68286 $notFoundSuffix = '()';
68287 $notFoundSuffixLen = \strlen($notFoundSuffix);
68288 if ($notFoundSuffixLen > $messageLen) {
68289 return;
68290 }
68291
68292 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
68293 return;
68294 }
68295
68296 $prefix = 'Call to undefined function ';
68297 $prefixLen = \strlen($prefix);
68298 if (0 !== strpos($error['message'], $prefix)) {
68299 return;
68300 }
68301
68302 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
68303 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
68304 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
68305 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
68306 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
68307 } else {
68308 $functionName = $fullyQualifiedFunctionName;
68309 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
68310 }
68311
68312 $candidates = array();
68313 foreach (get_defined_functions() as $type => $definedFunctionNames) {
68314 foreach ($definedFunctionNames as $definedFunctionName) {
68315 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
68316 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
68317 } else {
68318 $definedFunctionNameBasename = $definedFunctionName;
68319 }
68320
68321 if ($definedFunctionNameBasename === $functionName) {
68322 $candidates[] = '\\'.$definedFunctionName;
68323 }
68324 }
68325 }
68326
68327 if ($candidates) {
68328 sort($candidates);
68329 $last = array_pop($candidates).'"?';
68330 if ($candidates) {
68331 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
68332 } else {
68333 $candidates = '"'.$last;
68334 }
68335 $message .= "\nDid you mean to call ".$candidates;
68336 }
68337
68338 return new UndefinedFunctionException($message, $exception);
68339 }
68340 }
68341 <?php
68342
68343
68344
68345
68346
68347
68348
68349
68350
68351
68352 namespace Symfony\Component\Debug\FatalErrorHandler;
68353
68354 use Symfony\Component\Debug\Exception\FatalErrorException;
68355 use Symfony\Component\Debug\Exception\UndefinedMethodException;
68356
68357
68358
68359
68360
68361
68362 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
68363 {
68364
68365
68366
68367 public function handleError(array $error, FatalErrorException $exception)
68368 {
68369 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
68370 if (!$matches) {
68371 return;
68372 }
68373
68374 $className = $matches[1];
68375 $methodName = $matches[2];
68376
68377 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
68378
68379 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
68380
68381 return new UndefinedMethodException($message, $exception);
68382 }
68383
68384 $candidates = array();
68385 foreach ($methods as $definedMethodName) {
68386 $lev = levenshtein($methodName, $definedMethodName);
68387 if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
68388 $candidates[] = $definedMethodName;
68389 }
68390 }
68391
68392 if ($candidates) {
68393 sort($candidates);
68394 $last = array_pop($candidates).'"?';
68395 if ($candidates) {
68396 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
68397 } else {
68398 $candidates = '"'.$last;
68399 }
68400
68401 $message .= "\nDid you mean to call ".$candidates;
68402 }
68403
68404 return new UndefinedMethodException($message, $exception);
68405 }
68406 }
68407 Copyright (c) 2004-2018 Fabien Potencier
68408
68409 Permission is hereby granted, free of charge, to any person obtaining a copy
68410 of this software and associated documentation files (the "Software"), to deal
68411 in the Software without restriction, including without limitation the rights
68412 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68413 copies of the Software, and to permit persons to whom the Software is furnished
68414 to do so, subject to the following conditions:
68415
68416 The above copyright notice and this permission notice shall be included in all
68417 copies or substantial portions of the Software.
68418
68419 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68420 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68421 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68422 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68423 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68424 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68425 THE SOFTWARE.
68426 <?php
68427
68428
68429
68430
68431
68432
68433
68434
68435
68436
68437 namespace Symfony\Component\Filesystem\Exception;
68438
68439
68440
68441
68442
68443
68444 interface ExceptionInterface
68445 {
68446 }
68447 <?php
68448
68449
68450
68451
68452
68453
68454
68455
68456
68457
68458 namespace Symfony\Component\Filesystem\Exception;
68459
68460
68461
68462
68463
68464
68465
68466 class FileNotFoundException extends IOException
68467 {
68468 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
68469 {
68470 if (null === $message) {
68471 if (null === $path) {
68472 $message = 'File could not be found.';
68473 } else {
68474 $message = sprintf('File "%s" could not be found.', $path);
68475 }
68476 }
68477
68478 parent::__construct($message, $code, $previous, $path);
68479 }
68480 }
68481 <?php
68482
68483
68484
68485
68486
68487
68488
68489
68490
68491
68492 namespace Symfony\Component\Filesystem\Exception;
68493
68494
68495
68496
68497
68498
68499
68500
68501 class IOException extends \RuntimeException implements IOExceptionInterface
68502 {
68503 private $path;
68504
68505 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
68506 {
68507 $this->path = $path;
68508
68509 parent::__construct($message, $code, $previous);
68510 }
68511
68512
68513
68514
68515 public function getPath()
68516 {
68517 return $this->path;
68518 }
68519 }
68520 <?php
68521
68522
68523
68524
68525
68526
68527
68528
68529
68530
68531 namespace Symfony\Component\Filesystem\Exception;
68532
68533
68534
68535
68536
68537
68538 interface IOExceptionInterface extends ExceptionInterface
68539 {
68540
68541
68542
68543
68544
68545 public function getPath();
68546 }
68547 <?php
68548
68549
68550
68551
68552
68553
68554
68555
68556
68557
68558 namespace Symfony\Component\Filesystem;
68559
68560 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
68561 use Symfony\Component\Filesystem\Exception\IOException;
68562
68563
68564
68565
68566
68567
68568 class Filesystem
68569 {
68570 private static $lastError;
68571
68572
68573
68574
68575
68576
68577
68578
68579
68580
68581
68582
68583
68584
68585
68586 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
68587 {
68588 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
68589 if ($originIsLocal && !is_file($originFile)) {
68590 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
68591 }
68592
68593 $this->mkdir(\dirname($targetFile));
68594
68595 $doCopy = true;
68596 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
68597 $doCopy = filemtime($originFile) > filemtime($targetFile);
68598 }
68599
68600 if ($doCopy) {
68601
68602 if (false === $source = @fopen($originFile, 'r')) {
68603 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
68604 }
68605
68606
68607 if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
68608 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
68609 }
68610
68611 $bytesCopied = stream_copy_to_stream($source, $target);
68612 fclose($source);
68613 fclose($target);
68614 unset($source, $target);
68615
68616 if (!is_file($targetFile)) {
68617 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
68618 }
68619
68620 if ($originIsLocal) {
68621
68622 @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
68623
68624 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
68625 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);
68626 }
68627 }
68628 }
68629 }
68630
68631
68632
68633
68634
68635
68636
68637
68638
68639 public function mkdir($dirs, $mode = 0777)
68640 {
68641 foreach ($this->toIterator($dirs) as $dir) {
68642 if (is_dir($dir)) {
68643 continue;
68644 }
68645
68646 if (!self::box('mkdir', $dir, $mode, true)) {
68647 if (!is_dir($dir)) {
68648
68649 if (self::$lastError) {
68650 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
68651 }
68652 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
68653 }
68654 }
68655 }
68656 }
68657
68658
68659
68660
68661
68662
68663
68664
68665 public function exists($files)
68666 {
68667 $maxPathLength = PHP_MAXPATHLEN - 2;
68668
68669 foreach ($this->toIterator($files) as $file) {
68670 if (\strlen($file) > $maxPathLength) {
68671 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
68672 }
68673
68674 if (!file_exists($file)) {
68675 return false;
68676 }
68677 }
68678
68679 return true;
68680 }
68681
68682
68683
68684
68685
68686
68687
68688
68689
68690
68691 public function touch($files, $time = null, $atime = null)
68692 {
68693 foreach ($this->toIterator($files) as $file) {
68694 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
68695 if (true !== $touch) {
68696 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
68697 }
68698 }
68699 }
68700
68701
68702
68703
68704
68705
68706
68707
68708 public function remove($files)
68709 {
68710 if ($files instanceof \Traversable) {
68711 $files = iterator_to_array($files, false);
68712 } elseif (!\is_array($files)) {
68713 $files = array($files);
68714 }
68715 $files = array_reverse($files);
68716 foreach ($files as $file) {
68717 if (is_link($file)) {
68718
68719 if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
68720 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
68721 }
68722 } elseif (is_dir($file)) {
68723 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
68724
68725 if (!self::box('rmdir', $file) && file_exists($file)) {
68726 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
68727 }
68728 } elseif (!self::box('unlink', $file) && file_exists($file)) {
68729 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
68730 }
68731 }
68732 }
68733
68734
68735
68736
68737
68738
68739
68740
68741
68742
68743
68744 public function chmod($files, $mode, $umask = 0000, $recursive = false)
68745 {
68746 foreach ($this->toIterator($files) as $file) {
68747 if (true !== @chmod($file, $mode & ~$umask)) {
68748 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
68749 }
68750 if ($recursive && is_dir($file) && !is_link($file)) {
68751 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
68752 }
68753 }
68754 }
68755
68756
68757
68758
68759
68760
68761
68762
68763
68764
68765 public function chown($files, $user, $recursive = false)
68766 {
68767 foreach ($this->toIterator($files) as $file) {
68768 if ($recursive && is_dir($file) && !is_link($file)) {
68769 $this->chown(new \FilesystemIterator($file), $user, true);
68770 }
68771 if (is_link($file) && \function_exists('lchown')) {
68772 if (true !== @lchown($file, $user)) {
68773 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
68774 }
68775 } else {
68776 if (true !== @chown($file, $user)) {
68777 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
68778 }
68779 }
68780 }
68781 }
68782
68783
68784
68785
68786
68787
68788
68789
68790
68791
68792 public function chgrp($files, $group, $recursive = false)
68793 {
68794 foreach ($this->toIterator($files) as $file) {
68795 if ($recursive && is_dir($file) && !is_link($file)) {
68796 $this->chgrp(new \FilesystemIterator($file), $group, true);
68797 }
68798 if (is_link($file) && \function_exists('lchgrp')) {
68799 if (true !== @lchgrp($file, $group) || (\defined('HHVM_VERSION') && !posix_getgrnam($group))) {
68800 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
68801 }
68802 } else {
68803 if (true !== @chgrp($file, $group)) {
68804 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
68805 }
68806 }
68807 }
68808 }
68809
68810
68811
68812
68813
68814
68815
68816
68817
68818
68819
68820 public function rename($origin, $target, $overwrite = false)
68821 {
68822
68823 if (!$overwrite && $this->isReadable($target)) {
68824 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
68825 }
68826
68827 if (true !== @rename($origin, $target)) {
68828 if (is_dir($origin)) {
68829
68830 $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
68831 $this->remove($origin);
68832
68833 return;
68834 }
68835 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
68836 }
68837 }
68838
68839
68840
68841
68842
68843
68844
68845
68846
68847
68848 private function isReadable($filename)
68849 {
68850 $maxPathLength = PHP_MAXPATHLEN - 2;
68851
68852 if (\strlen($filename) > $maxPathLength) {
68853 throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
68854 }
68855
68856 return is_readable($filename);
68857 }
68858
68859
68860
68861
68862
68863
68864
68865
68866
68867
68868 public function symlink($originDir, $targetDir, $copyOnWindows = false)
68869 {
68870 if ('\\' === \DIRECTORY_SEPARATOR) {
68871 $originDir = strtr($originDir, '/', '\\');
68872 $targetDir = strtr($targetDir, '/', '\\');
68873
68874 if ($copyOnWindows) {
68875 $this->mirror($originDir, $targetDir);
68876
68877 return;
68878 }
68879 }
68880
68881 $this->mkdir(\dirname($targetDir));
68882
68883 if (is_link($targetDir)) {
68884 if (readlink($targetDir) === $originDir) {
68885 return;
68886 }
68887 $this->remove($targetDir);
68888 }
68889
68890 if (!self::box('symlink', $originDir, $targetDir)) {
68891 if (null !== self::$lastError) {
68892 if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
68893 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);
68894 }
68895 }
68896 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
68897 }
68898 }
68899
68900
68901
68902
68903
68904
68905
68906
68907
68908 public function makePathRelative($endPath, $startPath)
68909 {
68910
68911 if ('\\' === \DIRECTORY_SEPARATOR) {
68912 $endPath = str_replace('\\', '/', $endPath);
68913 $startPath = str_replace('\\', '/', $startPath);
68914 }
68915
68916 $stripDriveLetter = function ($path) {
68917 if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
68918 return substr($path, 2);
68919 }
68920
68921 return $path;
68922 };
68923
68924 $endPath = $stripDriveLetter($endPath);
68925 $startPath = $stripDriveLetter($startPath);
68926
68927
68928 $startPathArr = explode('/', trim($startPath, '/'));
68929 $endPathArr = explode('/', trim($endPath, '/'));
68930
68931 $normalizePathArray = function ($pathSegments, $absolute) {
68932 $result = array();
68933
68934 foreach ($pathSegments as $segment) {
68935 if ('..' === $segment && ($absolute || \count($result))) {
68936 array_pop($result);
68937 } elseif ('.' !== $segment) {
68938 $result[] = $segment;
68939 }
68940 }
68941
68942 return $result;
68943 };
68944
68945 $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
68946 $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
68947
68948
68949 $index = 0;
68950 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
68951 ++$index;
68952 }
68953
68954
68955 if (1 === \count($startPathArr) && '' === $startPathArr[0]) {
68956 $depth = 0;
68957 } else {
68958 $depth = \count($startPathArr) - $index;
68959 }
68960
68961
68962 $traverser = str_repeat('../', $depth);
68963
68964 $endPathRemainder = implode('/', \array_slice($endPathArr, $index));
68965
68966
68967 $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
68968
68969 return '' === $relativePath ? './' : $relativePath;
68970 }
68971
68972
68973
68974
68975
68976
68977
68978
68979
68980
68981
68982
68983
68984
68985
68986
68987
68988
68989
68990
68991 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
68992 {
68993 $targetDir = rtrim($targetDir, '/\\');
68994 $originDir = rtrim($originDir, '/\\');
68995 $originDirLen = \strlen($originDir);
68996
68997
68998 if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
68999 $deleteIterator = $iterator;
69000 if (null === $deleteIterator) {
69001 $flags = \FilesystemIterator::SKIP_DOTS;
69002 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
69003 }
69004 $targetDirLen = \strlen($targetDir);
69005 foreach ($deleteIterator as $file) {
69006 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
69007 if (!$this->exists($origin)) {
69008 $this->remove($file);
69009 }
69010 }
69011 }
69012
69013 $copyOnWindows = false;
69014 if (isset($options['copy_on_windows'])) {
69015 $copyOnWindows = $options['copy_on_windows'];
69016 }
69017
69018 if (null === $iterator) {
69019 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
69020 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
69021 }
69022
69023 if ($this->exists($originDir)) {
69024 $this->mkdir($targetDir);
69025 }
69026
69027 foreach ($iterator as $file) {
69028 $target = $targetDir.substr($file->getPathname(), $originDirLen);
69029
69030 if ($copyOnWindows) {
69031 if (is_file($file)) {
69032 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
69033 } elseif (is_dir($file)) {
69034 $this->mkdir($target);
69035 } else {
69036 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
69037 }
69038 } else {
69039 if (is_link($file)) {
69040 $this->symlink($file->getLinkTarget(), $target);
69041 } elseif (is_dir($file)) {
69042 $this->mkdir($target);
69043 } elseif (is_file($file)) {
69044 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
69045 } else {
69046 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
69047 }
69048 }
69049 }
69050 }
69051
69052
69053
69054
69055
69056
69057
69058
69059 public function isAbsolutePath($file)
69060 {
69061 return strspn($file, '/\\', 0, 1)
69062 || (\strlen($file) > 3 && ctype_alpha($file[0])
69063 && ':' === substr($file, 1, 1)
69064 && strspn($file, '/\\', 2, 1)
69065 )
69066 || null !== parse_url($file, PHP_URL_SCHEME)
69067 ;
69068 }
69069
69070
69071
69072
69073
69074
69075
69076
69077
69078
69079 public function tempnam($dir, $prefix)
69080 {
69081 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
69082
69083
69084 if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
69085 $tmpFile = @tempnam($hierarchy, $prefix);
69086
69087
69088 if (false !== $tmpFile) {
69089 if (null !== $scheme && 'gs' !== $scheme) {
69090 return $scheme.'://'.$tmpFile;
69091 }
69092
69093 return $tmpFile;
69094 }
69095
69096 throw new IOException('A temporary file could not be created.');
69097 }
69098
69099
69100 for ($i = 0; $i < 10; ++$i) {
69101
69102 $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
69103
69104
69105
69106 $handle = @fopen($tmpFile, 'x+');
69107
69108
69109 if (false === $handle) {
69110 continue;
69111 }
69112
69113
69114 @fclose($handle);
69115
69116 return $tmpFile;
69117 }
69118
69119 throw new IOException('A temporary file could not be created.');
69120 }
69121
69122
69123
69124
69125
69126
69127
69128
69129
69130
69131
69132 public function dumpFile($filename, $content, $mode = 0666)
69133 {
69134 $dir = \dirname($filename);
69135
69136 if (!is_dir($dir)) {
69137 $this->mkdir($dir);
69138 }
69139
69140 if (!is_writable($dir)) {
69141 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
69142 }
69143
69144 $tmpFile = $this->tempnam($dir, basename($filename));
69145
69146 if (false === @file_put_contents($tmpFile, $content)) {
69147 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
69148 }
69149
69150 if (null !== $mode) {
69151 if (\func_num_args() > 2) {
69152 @trigger_error('Support for modifying file permissions is deprecated since Symfony 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
69153 }
69154
69155 $this->chmod($tmpFile, $mode);
69156 } elseif (file_exists($filename)) {
69157 @chmod($tmpFile, fileperms($filename));
69158 }
69159
69160 $this->rename($tmpFile, $filename, true);
69161 }
69162
69163
69164
69165
69166
69167
69168 private function toIterator($files)
69169 {
69170 if (!$files instanceof \Traversable) {
69171 $files = new \ArrayObject(\is_array($files) ? $files : array($files));
69172 }
69173
69174 return $files;
69175 }
69176
69177
69178
69179
69180
69181
69182
69183
69184 private function getSchemeAndHierarchy($filename)
69185 {
69186 $components = explode('://', $filename, 2);
69187
69188 return 2 === \count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
69189 }
69190
69191 private static function box($func)
69192 {
69193 self::$lastError = null;
69194 \set_error_handler(__CLASS__.'::handleError');
69195 try {
69196 $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
69197 \restore_error_handler();
69198
69199 return $result;
69200 } catch (\Throwable $e) {
69201 } catch (\Exception $e) {
69202 }
69203 \restore_error_handler();
69204
69205 throw $e;
69206 }
69207
69208
69209
69210
69211 public static function handleError($type, $msg)
69212 {
69213 self::$lastError = $msg;
69214 }
69215 }
69216 Copyright (c) 2004-2018 Fabien Potencier
69217
69218 Permission is hereby granted, free of charge, to any person obtaining a copy
69219 of this software and associated documentation files (the "Software"), to deal
69220 in the Software without restriction, including without limitation the rights
69221 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
69222 copies of the Software, and to permit persons to whom the Software is furnished
69223 to do so, subject to the following conditions:
69224
69225 The above copyright notice and this permission notice shall be included in all
69226 copies or substantial portions of the Software.
69227
69228 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
69229 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69230 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
69231 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
69232 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
69233 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
69234 THE SOFTWARE.
69235 <?php
69236
69237
69238
69239
69240
69241
69242
69243
69244
69245
69246 namespace Symfony\Component\Filesystem;
69247
69248 use Symfony\Component\Filesystem\Exception\IOException;
69249
69250
69251
69252
69253
69254
69255
69256
69257
69258
69259
69260
69261
69262
69263 class LockHandler
69264 {
69265 private $file;
69266 private $handle;
69267
69268
69269
69270
69271
69272
69273
69274 public function __construct($name, $lockPath = null)
69275 {
69276 $lockPath = $lockPath ?: sys_get_temp_dir();
69277
69278 if (!is_dir($lockPath)) {
69279 $fs = new Filesystem();
69280 $fs->mkdir($lockPath);
69281 }
69282
69283 if (!is_writable($lockPath)) {
69284 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
69285 }
69286
69287 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
69288 }
69289
69290
69291
69292
69293
69294
69295
69296
69297
69298
69299 public function lock($blocking = false)
69300 {
69301 if ($this->handle) {
69302 return true;
69303 }
69304
69305 $error = null;
69306
69307
69308 set_error_handler(function ($errno, $msg) use (&$error) {
69309 $error = $msg;
69310 });
69311
69312 if (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
69313 if ($this->handle = fopen($this->file, 'x')) {
69314 chmod($this->file, 0666);
69315 } elseif (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
69316 usleep(100); 
69317 $this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r');
69318 }
69319 }
69320 restore_error_handler();
69321
69322 if (!$this->handle) {
69323 throw new IOException($error, 0, null, $this->file);
69324 }
69325
69326
69327
69328 if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
69329 fclose($this->handle);
69330 $this->handle = null;
69331
69332 return false;
69333 }
69334
69335 return true;
69336 }
69337
69338
69339
69340
69341 public function release()
69342 {
69343 if ($this->handle) {
69344 flock($this->handle, LOCK_UN | LOCK_NB);
69345 fclose($this->handle);
69346 $this->handle = null;
69347 }
69348 }
69349 }
69350 <?php
69351
69352
69353
69354
69355
69356
69357
69358
69359
69360
69361 namespace Symfony\Component\Finder\Adapter;
69362
69363 @trigger_error('The '.__NAMESPACE__.'\AbstractAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
69364
69365
69366
69367
69368
69369
69370
69371
69372 abstract class AbstractAdapter implements AdapterInterface
69373 {
69374 protected $followLinks = false;
69375 protected $mode = 0;
69376 protected $minDepth = 0;
69377 protected $maxDepth = PHP_INT_MAX;
69378 protected $exclude = array();
69379 protected $names = array();
69380 protected $notNames = array();
69381 protected $contains = array();
69382 protected $notContains = array();
69383 protected $sizes = array();
69384 protected $dates = array();
69385 protected $filters = array();
69386 protected $sort = false;
69387 protected $paths = array();
69388 protected $notPaths = array();
69389 protected $ignoreUnreadableDirs = false;
69390
69391 private static $areSupported = array();
69392
69393
69394
69395
69396 public function isSupported()
69397 {
69398 $name = $this->getName();
69399
69400 if (!array_key_exists($name, self::$areSupported)) {
69401 self::$areSupported[$name] = $this->canBeUsed();
69402 }
69403
69404 return self::$areSupported[$name];
69405 }
69406
69407
69408
69409
69410 public function setFollowLinks($followLinks)
69411 {
69412 $this->followLinks = $followLinks;
69413
69414 return $this;
69415 }
69416
69417
69418
69419
69420 public function setMode($mode)
69421 {
69422 $this->mode = $mode;
69423
69424 return $this;
69425 }
69426
69427
69428
69429
69430 public function setDepths(array $depths)
69431 {
69432 $this->minDepth = 0;
69433 $this->maxDepth = PHP_INT_MAX;
69434
69435 foreach ($depths as $comparator) {
69436 switch ($comparator->getOperator()) {
69437 case '>':
69438 $this->minDepth = $comparator->getTarget() + 1;
69439 break;
69440 case '>=':
69441 $this->minDepth = $comparator->getTarget();
69442 break;
69443 case '<':
69444 $this->maxDepth = $comparator->getTarget() - 1;
69445 break;
69446 case '<=':
69447 $this->maxDepth = $comparator->getTarget();
69448 break;
69449 default:
69450 $this->minDepth = $this->maxDepth = $comparator->getTarget();
69451 }
69452 }
69453
69454 return $this;
69455 }
69456
69457
69458
69459
69460 public function setExclude(array $exclude)
69461 {
69462 $this->exclude = $exclude;
69463
69464 return $this;
69465 }
69466
69467
69468
69469
69470 public function setNames(array $names)
69471 {
69472 $this->names = $names;
69473
69474 return $this;
69475 }
69476
69477
69478
69479
69480 public function setNotNames(array $notNames)
69481 {
69482 $this->notNames = $notNames;
69483
69484 return $this;
69485 }
69486
69487
69488
69489
69490 public function setContains(array $contains)
69491 {
69492 $this->contains = $contains;
69493
69494 return $this;
69495 }
69496
69497
69498
69499
69500 public function setNotContains(array $notContains)
69501 {
69502 $this->notContains = $notContains;
69503
69504 return $this;
69505 }
69506
69507
69508
69509
69510 public function setSizes(array $sizes)
69511 {
69512 $this->sizes = $sizes;
69513
69514 return $this;
69515 }
69516
69517
69518
69519
69520 public function setDates(array $dates)
69521 {
69522 $this->dates = $dates;
69523
69524 return $this;
69525 }
69526
69527
69528
69529
69530 public function setFilters(array $filters)
69531 {
69532 $this->filters = $filters;
69533
69534 return $this;
69535 }
69536
69537
69538
69539
69540 public function setSort($sort)
69541 {
69542 $this->sort = $sort;
69543
69544 return $this;
69545 }
69546
69547
69548
69549
69550 public function setPath(array $paths)
69551 {
69552 $this->paths = $paths;
69553
69554 return $this;
69555 }
69556
69557
69558
69559
69560 public function setNotPath(array $notPaths)
69561 {
69562 $this->notPaths = $notPaths;
69563
69564 return $this;
69565 }
69566
69567
69568
69569
69570 public function ignoreUnreadableDirs($ignore = true)
69571 {
69572 $this->ignoreUnreadableDirs = (bool) $ignore;
69573
69574 return $this;
69575 }
69576
69577
69578
69579
69580
69581
69582
69583
69584
69585
69586
69587
69588 abstract protected function canBeUsed();
69589 }
69590 <?php
69591
69592
69593
69594
69595
69596
69597
69598
69599
69600
69601 namespace Symfony\Component\Finder\Adapter;
69602
69603 @trigger_error('The '.__NAMESPACE__.'\AbstractFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
69604
69605 use Symfony\Component\Finder\Comparator\DateComparator;
69606 use Symfony\Component\Finder\Comparator\NumberComparator;
69607 use Symfony\Component\Finder\Exception\AccessDeniedException;
69608 use Symfony\Component\Finder\Expression\Expression;
69609 use Symfony\Component\Finder\Iterator;
69610 use Symfony\Component\Finder\Shell\Command;
69611 use Symfony\Component\Finder\Shell\Shell;
69612
69613
69614
69615
69616
69617
69618
69619
69620 abstract class AbstractFindAdapter extends AbstractAdapter
69621 {
69622 protected $shell;
69623
69624 public function __construct()
69625 {
69626 $this->shell = new Shell();
69627 }
69628
69629
69630
69631
69632 public function searchInDirectory($dir)
69633 {
69634
69635 $dir = realpath($dir);
69636
69637
69638 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
69639 return new Iterator\FilePathsIterator(array(), $dir);
69640 }
69641
69642 $command = Command::create();
69643 $find = $this->buildFindCommand($command, $dir);
69644
69645 if ($this->followLinks) {
69646 $find->add('-follow');
69647 }
69648
69649 $find->add('-mindepth')->add($this->minDepth + 1);
69650
69651 if (PHP_INT_MAX !== $this->maxDepth) {
69652 $find->add('-maxdepth')->add($this->maxDepth + 1);
69653 }
69654
69655 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
69656 $find->add('-type d');
69657 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
69658 $find->add('-type f');
69659 }
69660
69661 $this->buildNamesFiltering($find, $this->names);
69662 $this->buildNamesFiltering($find, $this->notNames, true);
69663 $this->buildPathsFiltering($find, $dir, $this->paths);
69664 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
69665 $this->buildSizesFiltering($find, $this->sizes);
69666 $this->buildDatesFiltering($find, $this->dates);
69667
69668 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
69669 $useSort = \is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
69670
69671 if ($useGrep && ($this->contains || $this->notContains)) {
69672 $grep = $command->ins('grep');
69673 $this->buildContentFiltering($grep, $this->contains);
69674 $this->buildContentFiltering($grep, $this->notContains, true);
69675 }
69676
69677 if ($useSort) {
69678 $this->buildSorting($command, $this->sort);
69679 }
69680
69681 $command->setErrorHandler(
69682 $this->ignoreUnreadableDirs
69683
69684 ? function ($stderr) { }
69685 : function ($stderr) { throw new AccessDeniedException($stderr); }
69686 );
69687
69688 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
69689 $iterator = new Iterator\FilePathsIterator($paths, $dir);
69690
69691 if ($this->exclude) {
69692 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
69693 }
69694
69695 if (!$useGrep && ($this->contains || $this->notContains)) {
69696 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
69697 }
69698
69699 if ($this->filters) {
69700 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
69701 }
69702
69703 if (!$useSort && $this->sort) {
69704 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
69705 $iterator = $iteratorAggregate->getIterator();
69706 }
69707
69708 return $iterator;
69709 }
69710
69711
69712
69713
69714 protected function canBeUsed()
69715 {
69716 return $this->shell->testCommand('find');
69717 }
69718
69719
69720
69721
69722
69723
69724
69725 protected function buildFindCommand(Command $command, $dir)
69726 {
69727 return $command
69728 ->ins('find')
69729 ->add('find ')
69730 ->arg($dir)
69731 ->add('-noleaf'); 
69732 }
69733
69734
69735
69736
69737
69738
69739 private function buildNamesFiltering(Command $command, array $names, $not = false)
69740 {
69741 if (0 === \count($names)) {
69742 return;
69743 }
69744
69745 $command->add($not ? '-not' : null)->cmd('(');
69746
69747 foreach ($names as $i => $name) {
69748 $expr = Expression::create($name);
69749
69750
69751 if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
69752 $expr = Expression::create($expr->getGlob()->toRegex(false));
69753 }
69754
69755
69756
69757
69758 if ($expr->isRegex()) {
69759 $regex = $expr->getRegex();
69760 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
69761 ->setStartFlag(false)
69762 ->setStartJoker(true)
69763 ->replaceJokers('[^/]');
69764 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
69765 $regex->setEndJoker(false)->append('[^/]*');
69766 }
69767 }
69768
69769 $command
69770 ->add($i > 0 ? '-or' : null)
69771 ->add($expr->isRegex()
69772 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
69773 : ($expr->isCaseSensitive() ? '-name' : '-iname')
69774 )
69775 ->arg($expr->renderPattern());
69776 }
69777
69778 $command->cmd(')');
69779 }
69780
69781
69782
69783
69784
69785
69786
69787 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
69788 {
69789 if (0 === \count($paths)) {
69790 return;
69791 }
69792
69793 $command->add($not ? '-not' : null)->cmd('(');
69794
69795 foreach ($paths as $i => $path) {
69796 $expr = Expression::create($path);
69797
69798
69799 if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
69800 $expr = Expression::create($expr->getGlob()->toRegex(false));
69801 }
69802
69803
69804 if ($expr->isRegex()) {
69805 $regex = $expr->getRegex();
69806 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).\DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
69807 } else {
69808 $expr->prepend('*')->append('*');
69809 }
69810
69811 $command
69812 ->add($i > 0 ? '-or' : null)
69813 ->add($expr->isRegex()
69814 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
69815 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
69816 )
69817 ->arg($expr->renderPattern());
69818 }
69819
69820 $command->cmd(')');
69821 }
69822
69823
69824
69825
69826
69827 private function buildSizesFiltering(Command $command, array $sizes)
69828 {
69829 foreach ($sizes as $i => $size) {
69830 $command->add($i > 0 ? '-and' : null);
69831
69832 switch ($size->getOperator()) {
69833 case '<=':
69834 $command->add('-size -'.($size->getTarget() + 1).'c');
69835 break;
69836 case '>=':
69837 $command->add('-size +'.($size->getTarget() - 1).'c');
69838 break;
69839 case '>':
69840 $command->add('-size +'.$size->getTarget().'c');
69841 break;
69842 case '!=':
69843 $command->add('-size -'.$size->getTarget().'c');
69844 $command->add('-size +'.$size->getTarget().'c');
69845 break;
69846 case '<':
69847 default:
69848 $command->add('-size -'.$size->getTarget().'c');
69849 }
69850 }
69851 }
69852
69853
69854
69855
69856
69857 private function buildDatesFiltering(Command $command, array $dates)
69858 {
69859 foreach ($dates as $i => $date) {
69860 $command->add($i > 0 ? '-and' : null);
69861
69862 $mins = (int) round((time() - $date->getTarget()) / 60);
69863
69864 if (0 > $mins) {
69865
69866 $command->add(' -mmin -0');
69867
69868 return;
69869 }
69870
69871 switch ($date->getOperator()) {
69872 case '<=':
69873 $command->add('-mmin +'.($mins - 1));
69874 break;
69875 case '>=':
69876 $command->add('-mmin -'.($mins + 1));
69877 break;
69878 case '>':
69879 $command->add('-mmin -'.$mins);
69880 break;
69881 case '!=':
69882 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
69883 break;
69884 case '<':
69885 default:
69886 $command->add('-mmin +'.$mins);
69887 }
69888 }
69889 }
69890
69891
69892
69893
69894
69895
69896
69897 private function buildSorting(Command $command, $sort)
69898 {
69899 $this->buildFormatSorting($command, $sort);
69900 }
69901
69902
69903
69904
69905
69906 abstract protected function buildFormatSorting(Command $command, $sort);
69907
69908
69909
69910
69911
69912
69913 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
69914 }
69915 <?php
69916
69917
69918
69919
69920
69921
69922
69923
69924
69925
69926 namespace Symfony\Component\Finder\Adapter;
69927
69928
69929
69930
69931
69932
69933 interface AdapterInterface
69934 {
69935
69936
69937
69938
69939
69940 public function setFollowLinks($followLinks);
69941
69942
69943
69944
69945
69946
69947 public function setMode($mode);
69948
69949
69950
69951
69952 public function setExclude(array $exclude);
69953
69954
69955
69956
69957 public function setDepths(array $depths);
69958
69959
69960
69961
69962 public function setNames(array $names);
69963
69964
69965
69966
69967 public function setNotNames(array $notNames);
69968
69969
69970
69971
69972 public function setContains(array $contains);
69973
69974
69975
69976
69977 public function setNotContains(array $notContains);
69978
69979
69980
69981
69982 public function setSizes(array $sizes);
69983
69984
69985
69986
69987 public function setDates(array $dates);
69988
69989
69990
69991
69992 public function setFilters(array $filters);
69993
69994
69995
69996
69997
69998
69999 public function setSort($sort);
70000
70001
70002
70003
70004 public function setPath(array $paths);
70005
70006
70007
70008
70009 public function setNotPath(array $notPaths);
70010
70011
70012
70013
70014
70015
70016 public function ignoreUnreadableDirs($ignore = true);
70017
70018
70019
70020
70021
70022
70023 public function searchInDirectory($dir);
70024
70025
70026
70027
70028
70029
70030 public function isSupported();
70031
70032
70033
70034
70035
70036
70037 public function getName();
70038 }
70039 <?php
70040
70041
70042
70043
70044
70045
70046
70047
70048
70049
70050 namespace Symfony\Component\Finder\Adapter;
70051
70052 @trigger_error('The '.__NAMESPACE__.'\BsdFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
70053
70054 use Symfony\Component\Finder\Expression\Expression;
70055 use Symfony\Component\Finder\Iterator\SortableIterator;
70056 use Symfony\Component\Finder\Shell\Command;
70057 use Symfony\Component\Finder\Shell\Shell;
70058
70059
70060
70061
70062
70063
70064
70065
70066 class BsdFindAdapter extends AbstractFindAdapter
70067 {
70068
70069
70070
70071 public function getName()
70072 {
70073 return 'bsd_find';
70074 }
70075
70076
70077
70078
70079 protected function canBeUsed()
70080 {
70081 return \in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
70082 }
70083
70084
70085
70086
70087 protected function buildFormatSorting(Command $command, $sort)
70088 {
70089 switch ($sort) {
70090 case SortableIterator::SORT_BY_NAME:
70091 $command->ins('sort')->add('| sort');
70092
70093 return;
70094 case SortableIterator::SORT_BY_TYPE:
70095 $format = '%HT';
70096 break;
70097 case SortableIterator::SORT_BY_ACCESSED_TIME:
70098 $format = '%a';
70099 break;
70100 case SortableIterator::SORT_BY_CHANGED_TIME:
70101 $format = '%c';
70102 break;
70103 case SortableIterator::SORT_BY_MODIFIED_TIME:
70104 $format = '%m';
70105 break;
70106 default:
70107 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
70108 }
70109
70110 $command
70111 ->add('-print0 | xargs -0 stat -f')
70112 ->arg($format.'%t%N')
70113 ->add('| sort | cut -f 2');
70114 }
70115
70116
70117
70118
70119 protected function buildFindCommand(Command $command, $dir)
70120 {
70121 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
70122
70123 return $command;
70124 }
70125
70126
70127
70128
70129 protected function buildContentFiltering(Command $command, array $contains, $not = false)
70130 {
70131 foreach ($contains as $contain) {
70132 $expr = Expression::create($contain);
70133
70134
70135 $command
70136 ->add('| grep -v \'^$\'')
70137 ->add('| xargs -I{} grep -I')
70138 ->add($expr->isCaseSensitive() ? null : '-i')
70139 ->add($not ? '-L' : '-l')
70140 ->add('-Ee')->arg($expr->renderPattern())
70141 ->add('{}')
70142 ;
70143 }
70144 }
70145 }
70146 <?php
70147
70148
70149
70150
70151
70152
70153
70154
70155
70156
70157 namespace Symfony\Component\Finder\Adapter;
70158
70159 @trigger_error('The '.__NAMESPACE__.'\GnuFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
70160
70161 use Symfony\Component\Finder\Expression\Expression;
70162 use Symfony\Component\Finder\Iterator\SortableIterator;
70163 use Symfony\Component\Finder\Shell\Command;
70164 use Symfony\Component\Finder\Shell\Shell;
70165
70166
70167
70168
70169
70170
70171
70172
70173 class GnuFindAdapter extends AbstractFindAdapter
70174 {
70175
70176
70177
70178 public function getName()
70179 {
70180 return 'gnu_find';
70181 }
70182
70183
70184
70185
70186 protected function buildFormatSorting(Command $command, $sort)
70187 {
70188 switch ($sort) {
70189 case SortableIterator::SORT_BY_NAME:
70190 $command->ins('sort')->add('| sort');
70191
70192 return;
70193 case SortableIterator::SORT_BY_TYPE:
70194 $format = '%y';
70195 break;
70196 case SortableIterator::SORT_BY_ACCESSED_TIME:
70197 $format = '%A@';
70198 break;
70199 case SortableIterator::SORT_BY_CHANGED_TIME:
70200 $format = '%C@';
70201 break;
70202 case SortableIterator::SORT_BY_MODIFIED_TIME:
70203 $format = '%T@';
70204 break;
70205 default:
70206 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
70207 }
70208
70209 $command
70210 ->get('find')
70211 ->add('-printf')
70212 ->arg($format.' %h/%f\\n')
70213 ->add('| sort | cut')
70214 ->arg('-d ')
70215 ->arg('-f2-')
70216 ;
70217 }
70218
70219
70220
70221
70222 protected function canBeUsed()
70223 {
70224 return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
70225 }
70226
70227
70228
70229
70230 protected function buildFindCommand(Command $command, $dir)
70231 {
70232 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
70233 }
70234
70235
70236
70237
70238 protected function buildContentFiltering(Command $command, array $contains, $not = false)
70239 {
70240 foreach ($contains as $contain) {
70241 $expr = Expression::create($contain);
70242
70243
70244 $command
70245 ->add('| xargs -I{} -r grep -I')
70246 ->add($expr->isCaseSensitive() ? null : '-i')
70247 ->add($not ? '-L' : '-l')
70248 ->add('-Ee')->arg($expr->renderPattern())
70249 ->add('{}')
70250 ;
70251 }
70252 }
70253 }
70254 <?php
70255
70256
70257
70258
70259
70260
70261
70262
70263
70264
70265 namespace Symfony\Component\Finder\Adapter;
70266
70267 @trigger_error('The '.__NAMESPACE__.'\PhpAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
70268
70269 use Symfony\Component\Finder\Iterator;
70270
70271
70272
70273
70274
70275
70276
70277
70278 class PhpAdapter extends AbstractAdapter
70279 {
70280
70281
70282
70283 public function searchInDirectory($dir)
70284 {
70285 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
70286
70287 if ($this->followLinks) {
70288 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
70289 }
70290
70291 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
70292
70293 if ($this->exclude) {
70294 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
70295 }
70296
70297 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
70298
70299 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
70300 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
70301 }
70302
70303 if ($this->mode) {
70304 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
70305 }
70306
70307 if ($this->names || $this->notNames) {
70308 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
70309 }
70310
70311 if ($this->contains || $this->notContains) {
70312 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
70313 }
70314
70315 if ($this->sizes) {
70316 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
70317 }
70318
70319 if ($this->dates) {
70320 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
70321 }
70322
70323 if ($this->filters) {
70324 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
70325 }
70326
70327 if ($this->paths || $this->notPaths) {
70328 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
70329 }
70330
70331 if ($this->sort) {
70332 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
70333 $iterator = $iteratorAggregate->getIterator();
70334 }
70335
70336 return $iterator;
70337 }
70338
70339
70340
70341
70342 public function getName()
70343 {
70344 return 'php';
70345 }
70346
70347
70348
70349
70350 protected function canBeUsed()
70351 {
70352 return true;
70353 }
70354 }
70355 <?php
70356
70357
70358
70359
70360
70361
70362
70363
70364
70365
70366 namespace Symfony\Component\Finder\Comparator;
70367
70368
70369
70370
70371
70372
70373 class Comparator
70374 {
70375 private $target;
70376 private $operator = '==';
70377
70378
70379
70380
70381
70382
70383 public function getTarget()
70384 {
70385 return $this->target;
70386 }
70387
70388
70389
70390
70391
70392
70393 public function setTarget($target)
70394 {
70395 $this->target = $target;
70396 }
70397
70398
70399
70400
70401
70402
70403 public function getOperator()
70404 {
70405 return $this->operator;
70406 }
70407
70408
70409
70410
70411
70412
70413
70414
70415 public function setOperator($operator)
70416 {
70417 if (!$operator) {
70418 $operator = '==';
70419 }
70420
70421 if (!\in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
70422 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
70423 }
70424
70425 $this->operator = $operator;
70426 }
70427
70428
70429
70430
70431
70432
70433
70434
70435 public function test($test)
70436 {
70437 switch ($this->operator) {
70438 case '>':
70439 return $test > $this->target;
70440 case '>=':
70441 return $test >= $this->target;
70442 case '<':
70443 return $test < $this->target;
70444 case '<=':
70445 return $test <= $this->target;
70446 case '!=':
70447 return $test != $this->target;
70448 }
70449
70450 return $test == $this->target;
70451 }
70452 }
70453 <?php
70454
70455
70456
70457
70458
70459
70460
70461
70462
70463
70464 namespace Symfony\Component\Finder\Comparator;
70465
70466
70467
70468
70469
70470
70471 class DateComparator extends Comparator
70472 {
70473
70474
70475
70476
70477
70478 public function __construct($test)
70479 {
70480 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
70481 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
70482 }
70483
70484 try {
70485 $date = new \DateTime($matches[2]);
70486 $target = $date->format('U');
70487 } catch (\Exception $e) {
70488 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
70489 }
70490
70491 $operator = isset($matches[1]) ? $matches[1] : '==';
70492 if ('since' === $operator || 'after' === $operator) {
70493 $operator = '>';
70494 }
70495
70496 if ('until' === $operator || 'before' === $operator) {
70497 $operator = '<';
70498 }
70499
70500 $this->setOperator($operator);
70501 $this->setTarget($target);
70502 }
70503 }
70504 <?php
70505
70506
70507
70508
70509
70510
70511
70512
70513
70514
70515 namespace Symfony\Component\Finder\Comparator;
70516
70517
70518
70519
70520
70521
70522
70523
70524
70525
70526
70527
70528
70529
70530
70531
70532
70533
70534
70535
70536
70537
70538 class NumberComparator extends Comparator
70539 {
70540
70541
70542
70543
70544
70545 public function __construct($test)
70546 {
70547 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
70548 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
70549 }
70550
70551 $target = $matches[2];
70552 if (!is_numeric($target)) {
70553 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
70554 }
70555 if (isset($matches[3])) {
70556
70557 switch (strtolower($matches[3])) {
70558 case 'k':
70559 $target *= 1000;
70560 break;
70561 case 'ki':
70562 $target *= 1024;
70563 break;
70564 case 'm':
70565 $target *= 1000000;
70566 break;
70567 case 'mi':
70568 $target *= 1024 * 1024;
70569 break;
70570 case 'g':
70571 $target *= 1000000000;
70572 break;
70573 case 'gi':
70574 $target *= 1024 * 1024 * 1024;
70575 break;
70576 }
70577 }
70578
70579 $this->setTarget($target);
70580 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
70581 }
70582 }
70583 <?php
70584
70585
70586
70587
70588
70589
70590
70591
70592
70593
70594 namespace Symfony\Component\Finder\Exception;
70595
70596
70597
70598
70599 class AccessDeniedException extends \UnexpectedValueException
70600 {
70601 }
70602 <?php
70603
70604
70605
70606
70607
70608
70609
70610
70611
70612
70613 namespace Symfony\Component\Finder\Exception;
70614
70615 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70616
70617 use Symfony\Component\Finder\Adapter\AdapterInterface;
70618
70619
70620
70621
70622
70623
70624
70625
70626 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
70627 {
70628 private $adapter;
70629
70630
70631
70632
70633
70634
70635 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
70636 {
70637 $this->adapter = $adapter;
70638 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
70639 }
70640
70641
70642
70643
70644 public function getAdapter()
70645 {
70646 return $this->adapter;
70647 }
70648 }
70649 <?php
70650
70651
70652
70653
70654
70655
70656
70657
70658
70659
70660 namespace Symfony\Component\Finder\Exception;
70661
70662
70663
70664
70665 interface ExceptionInterface
70666 {
70667
70668
70669
70670 public function getAdapter();
70671 }
70672 <?php
70673
70674
70675
70676
70677
70678
70679
70680
70681
70682
70683 namespace Symfony\Component\Finder\Exception;
70684
70685 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70686
70687
70688
70689
70690
70691
70692 class OperationNotPermitedException extends AdapterFailureException
70693 {
70694 }
70695 <?php
70696
70697
70698
70699
70700
70701
70702
70703
70704
70705
70706 namespace Symfony\Component\Finder\Exception;
70707
70708 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70709
70710 use Symfony\Component\Finder\Adapter\AdapterInterface;
70711 use Symfony\Component\Finder\Shell\Command;
70712
70713
70714
70715
70716
70717
70718 class ShellCommandFailureException extends AdapterFailureException
70719 {
70720 private $command;
70721
70722 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
70723 {
70724 $this->command = $command;
70725 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
70726 }
70727
70728
70729
70730
70731 public function getCommand()
70732 {
70733 return $this->command;
70734 }
70735 }
70736 <?php
70737
70738
70739
70740
70741
70742
70743
70744
70745
70746
70747 namespace Symfony\Component\Finder\Expression;
70748
70749 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70750
70751
70752
70753
70754 class Expression implements ValueInterface
70755 {
70756 const TYPE_REGEX = 1;
70757 const TYPE_GLOB = 2;
70758
70759
70760
70761
70762 private $value;
70763
70764
70765
70766
70767
70768
70769 public static function create($expr)
70770 {
70771 return new self($expr);
70772 }
70773
70774
70775
70776
70777 public function __construct($expr)
70778 {
70779 try {
70780 $this->value = Regex::create($expr);
70781 } catch (\InvalidArgumentException $e) {
70782 $this->value = new Glob($expr);
70783 }
70784 }
70785
70786
70787
70788
70789 public function __toString()
70790 {
70791 return $this->render();
70792 }
70793
70794
70795
70796
70797 public function render()
70798 {
70799 return $this->value->render();
70800 }
70801
70802
70803
70804
70805 public function renderPattern()
70806 {
70807 return $this->value->renderPattern();
70808 }
70809
70810
70811
70812
70813 public function isCaseSensitive()
70814 {
70815 return $this->value->isCaseSensitive();
70816 }
70817
70818
70819
70820
70821 public function getType()
70822 {
70823 return $this->value->getType();
70824 }
70825
70826
70827
70828
70829 public function prepend($expr)
70830 {
70831 $this->value->prepend($expr);
70832
70833 return $this;
70834 }
70835
70836
70837
70838
70839 public function append($expr)
70840 {
70841 $this->value->append($expr);
70842
70843 return $this;
70844 }
70845
70846
70847
70848
70849 public function isRegex()
70850 {
70851 return self::TYPE_REGEX === $this->value->getType();
70852 }
70853
70854
70855
70856
70857 public function isGlob()
70858 {
70859 return self::TYPE_GLOB === $this->value->getType();
70860 }
70861
70862
70863
70864
70865
70866
70867 public function getGlob()
70868 {
70869 if (self::TYPE_GLOB !== $this->value->getType()) {
70870 throw new \LogicException('Regex can\'t be transformed to glob.');
70871 }
70872
70873 return $this->value;
70874 }
70875
70876
70877
70878
70879 public function getRegex()
70880 {
70881 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
70882 }
70883 }
70884 <?php
70885
70886
70887
70888
70889
70890
70891
70892
70893
70894
70895 namespace Symfony\Component\Finder\Expression;
70896
70897 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70898
70899 use Symfony\Component\Finder\Glob as FinderGlob;
70900
70901
70902
70903
70904 class Glob implements ValueInterface
70905 {
70906 private $pattern;
70907
70908
70909
70910
70911 public function __construct($pattern)
70912 {
70913 $this->pattern = $pattern;
70914 }
70915
70916
70917
70918
70919 public function render()
70920 {
70921 return $this->pattern;
70922 }
70923
70924
70925
70926
70927 public function renderPattern()
70928 {
70929 return $this->pattern;
70930 }
70931
70932
70933
70934
70935 public function getType()
70936 {
70937 return Expression::TYPE_GLOB;
70938 }
70939
70940
70941
70942
70943 public function isCaseSensitive()
70944 {
70945 return true;
70946 }
70947
70948
70949
70950
70951 public function prepend($expr)
70952 {
70953 $this->pattern = $expr.$this->pattern;
70954
70955 return $this;
70956 }
70957
70958
70959
70960
70961 public function append($expr)
70962 {
70963 $this->pattern .= $expr;
70964
70965 return $this;
70966 }
70967
70968
70969
70970
70971
70972
70973 public function isExpandable()
70974 {
70975 return false !== strpos($this->pattern, '{')
70976 && false !== strpos($this->pattern, '}');
70977 }
70978
70979
70980
70981
70982
70983
70984
70985 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
70986 {
70987 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
70988
70989 return new Regex($regex);
70990 }
70991 }
70992 <?php
70993
70994
70995
70996
70997
70998
70999
71000
71001
71002
71003 namespace Symfony\Component\Finder\Expression;
71004
71005 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71006
71007
71008
71009
71010 class Regex implements ValueInterface
71011 {
71012 const START_FLAG = '^';
71013 const END_FLAG = '$';
71014 const BOUNDARY = '~';
71015 const JOKER = '.*';
71016 const ESCAPING = '\\';
71017
71018
71019
71020
71021 private $pattern;
71022
71023
71024
71025
71026 private $options;
71027
71028
71029
71030
71031 private $startFlag;
71032
71033
71034
71035
71036 private $endFlag;
71037
71038
71039
71040
71041 private $startJoker;
71042
71043
71044
71045
71046 private $endJoker;
71047
71048
71049
71050
71051
71052
71053
71054
71055 public static function create($expr)
71056 {
71057 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
71058 $start = substr($m[1], 0, 1);
71059 $end = substr($m[1], -1);
71060
71061 if (
71062 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
71063 || ('{' === $start && '}' === $end)
71064 || ('(' === $start && ')' === $end)
71065 ) {
71066 return new self(substr($m[1], 1, -1), $m[2], $end);
71067 }
71068 }
71069
71070 throw new \InvalidArgumentException('Given expression is not a regex.');
71071 }
71072
71073
71074
71075
71076
71077
71078 public function __construct($pattern, $options = '', $delimiter = null)
71079 {
71080 if (null !== $delimiter) {
71081
71082 $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
71083 }
71084
71085 $this->parsePattern($pattern);
71086 $this->options = $options;
71087 }
71088
71089
71090
71091
71092 public function __toString()
71093 {
71094 return $this->render();
71095 }
71096
71097
71098
71099
71100 public function render()
71101 {
71102 return self::BOUNDARY
71103 .$this->renderPattern()
71104 .self::BOUNDARY
71105 .$this->options;
71106 }
71107
71108
71109
71110
71111 public function renderPattern()
71112 {
71113 return ($this->startFlag ? self::START_FLAG : '')
71114 .($this->startJoker ? self::JOKER : '')
71115 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
71116 .($this->endJoker ? self::JOKER : '')
71117 .($this->endFlag ? self::END_FLAG : '');
71118 }
71119
71120
71121
71122
71123 public function isCaseSensitive()
71124 {
71125 return !$this->hasOption('i');
71126 }
71127
71128
71129
71130
71131 public function getType()
71132 {
71133 return Expression::TYPE_REGEX;
71134 }
71135
71136
71137
71138
71139 public function prepend($expr)
71140 {
71141 $this->pattern = $expr.$this->pattern;
71142
71143 return $this;
71144 }
71145
71146
71147
71148
71149 public function append($expr)
71150 {
71151 $this->pattern .= $expr;
71152
71153 return $this;
71154 }
71155
71156
71157
71158
71159
71160
71161 public function hasOption($option)
71162 {
71163 return false !== strpos($this->options, $option);
71164 }
71165
71166
71167
71168
71169
71170
71171 public function addOption($option)
71172 {
71173 if (!$this->hasOption($option)) {
71174 $this->options .= $option;
71175 }
71176
71177 return $this;
71178 }
71179
71180
71181
71182
71183
71184
71185 public function removeOption($option)
71186 {
71187 $this->options = str_replace($option, '', $this->options);
71188
71189 return $this;
71190 }
71191
71192
71193
71194
71195
71196
71197 public function setStartFlag($startFlag)
71198 {
71199 $this->startFlag = $startFlag;
71200
71201 return $this;
71202 }
71203
71204
71205
71206
71207 public function hasStartFlag()
71208 {
71209 return $this->startFlag;
71210 }
71211
71212
71213
71214
71215
71216
71217 public function setEndFlag($endFlag)
71218 {
71219 $this->endFlag = (bool) $endFlag;
71220
71221 return $this;
71222 }
71223
71224
71225
71226
71227 public function hasEndFlag()
71228 {
71229 return $this->endFlag;
71230 }
71231
71232
71233
71234
71235
71236
71237 public function setStartJoker($startJoker)
71238 {
71239 $this->startJoker = $startJoker;
71240
71241 return $this;
71242 }
71243
71244
71245
71246
71247 public function hasStartJoker()
71248 {
71249 return $this->startJoker;
71250 }
71251
71252
71253
71254
71255
71256
71257 public function setEndJoker($endJoker)
71258 {
71259 $this->endJoker = (bool) $endJoker;
71260
71261 return $this;
71262 }
71263
71264
71265
71266
71267 public function hasEndJoker()
71268 {
71269 return $this->endJoker;
71270 }
71271
71272
71273
71274
71275 public function replaceJokers($replacement)
71276 {
71277 $replace = function ($subject) use ($replacement) {
71278 $subject = $subject[0];
71279 $replace = 0 === substr_count($subject, '\\') % 2;
71280
71281 return $replace ? str_replace('.', $replacement, $subject) : $subject;
71282 };
71283
71284 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
71285
71286 return $this;
71287 }
71288
71289
71290
71291
71292 private function parsePattern($pattern)
71293 {
71294 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
71295 $pattern = substr($pattern, 1);
71296 }
71297
71298 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
71299 $pattern = substr($pattern, 2);
71300 }
71301
71302 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
71303 $pattern = substr($pattern, 0, -1);
71304 }
71305
71306 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
71307 $pattern = substr($pattern, 0, -2);
71308 }
71309
71310 $this->pattern = $pattern;
71311 }
71312 }
71313 <?php
71314
71315
71316
71317
71318
71319
71320
71321
71322
71323
71324 namespace Symfony\Component\Finder\Expression;
71325
71326 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71327
71328
71329
71330
71331 interface ValueInterface
71332 {
71333
71334
71335
71336
71337
71338 public function render();
71339
71340
71341
71342
71343
71344
71345 public function renderPattern();
71346
71347
71348
71349
71350
71351
71352 public function isCaseSensitive();
71353
71354
71355
71356
71357
71358
71359 public function getType();
71360
71361
71362
71363
71364
71365
71366 public function prepend($expr);
71367
71368
71369
71370
71371
71372
71373 public function append($expr);
71374 }
71375 <?php
71376
71377
71378
71379
71380
71381
71382
71383
71384
71385
71386 namespace Symfony\Component\Finder;
71387
71388 use Symfony\Component\Finder\Adapter\AdapterInterface;
71389 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
71390 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
71391 use Symfony\Component\Finder\Adapter\PhpAdapter;
71392 use Symfony\Component\Finder\Comparator\DateComparator;
71393 use Symfony\Component\Finder\Comparator\NumberComparator;
71394 use Symfony\Component\Finder\Exception\ExceptionInterface;
71395 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
71396 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
71397 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
71398 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
71399 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
71400 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
71401 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
71402 use Symfony\Component\Finder\Iterator\SortableIterator;
71403
71404
71405
71406
71407
71408
71409
71410
71411
71412
71413
71414
71415
71416
71417 class Finder implements \IteratorAggregate, \Countable
71418 {
71419 const IGNORE_VCS_FILES = 1;
71420 const IGNORE_DOT_FILES = 2;
71421
71422 private $mode = 0;
71423 private $names = array();
71424 private $notNames = array();
71425 private $exclude = array();
71426 private $filters = array();
71427 private $depths = array();
71428 private $sizes = array();
71429 private $followLinks = false;
71430 private $sort = false;
71431 private $ignore = 0;
71432 private $dirs = array();
71433 private $dates = array();
71434 private $iterators = array();
71435 private $contains = array();
71436 private $notContains = array();
71437 private $adapters = null;
71438 private $paths = array();
71439 private $notPaths = array();
71440 private $ignoreUnreadableDirs = false;
71441
71442 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
71443
71444 public function __construct()
71445 {
71446 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
71447 }
71448
71449
71450
71451
71452
71453
71454 public static function create()
71455 {
71456 return new static();
71457 }
71458
71459
71460
71461
71462
71463
71464
71465
71466
71467
71468
71469 public function addAdapter(AdapterInterface $adapter, $priority = 0)
71470 {
71471 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71472
71473 $this->initDefaultAdapters();
71474
71475 $this->adapters[$adapter->getName()] = array(
71476 'adapter' => $adapter,
71477 'priority' => $priority,
71478 'selected' => false,
71479 );
71480
71481 return $this->sortAdapters();
71482 }
71483
71484
71485
71486
71487
71488
71489
71490
71491 public function useBestAdapter()
71492 {
71493 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71494
71495 $this->initDefaultAdapters();
71496
71497 $this->resetAdapterSelection();
71498
71499 return $this->sortAdapters();
71500 }
71501
71502
71503
71504
71505
71506
71507
71508
71509
71510
71511
71512
71513 public function setAdapter($name)
71514 {
71515 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71516
71517 $this->initDefaultAdapters();
71518
71519 if (!isset($this->adapters[$name])) {
71520 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
71521 }
71522
71523 $this->resetAdapterSelection();
71524 $this->adapters[$name]['selected'] = true;
71525
71526 return $this->sortAdapters();
71527 }
71528
71529
71530
71531
71532
71533
71534
71535
71536 public function removeAdapters()
71537 {
71538 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71539
71540 $this->adapters = array();
71541
71542 return $this;
71543 }
71544
71545
71546
71547
71548
71549
71550
71551
71552 public function getAdapters()
71553 {
71554 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71555
71556 $this->initDefaultAdapters();
71557
71558 return array_values(array_map(function (array $adapter) {
71559 return $adapter['adapter'];
71560 }, $this->adapters));
71561 }
71562
71563
71564
71565
71566
71567
71568 public function directories()
71569 {
71570 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
71571
71572 return $this;
71573 }
71574
71575
71576
71577
71578
71579
71580 public function files()
71581 {
71582 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
71583
71584 return $this;
71585 }
71586
71587
71588
71589
71590
71591
71592
71593
71594
71595
71596
71597
71598
71599
71600
71601
71602 public function depth($level)
71603 {
71604 $this->depths[] = new Comparator\NumberComparator($level);
71605
71606 return $this;
71607 }
71608
71609
71610
71611
71612
71613
71614
71615
71616
71617
71618
71619
71620
71621
71622
71623
71624
71625
71626
71627 public function date($date)
71628 {
71629 $this->dates[] = new Comparator\DateComparator($date);
71630
71631 return $this;
71632 }
71633
71634
71635
71636
71637
71638
71639
71640
71641
71642
71643
71644
71645
71646
71647
71648
71649 public function name($pattern)
71650 {
71651 $this->names[] = $pattern;
71652
71653 return $this;
71654 }
71655
71656
71657
71658
71659
71660
71661
71662
71663
71664
71665 public function notName($pattern)
71666 {
71667 $this->notNames[] = $pattern;
71668
71669 return $this;
71670 }
71671
71672
71673
71674
71675
71676
71677
71678
71679
71680
71681
71682
71683
71684
71685
71686 public function contains($pattern)
71687 {
71688 $this->contains[] = $pattern;
71689
71690 return $this;
71691 }
71692
71693
71694
71695
71696
71697
71698
71699
71700
71701
71702
71703
71704
71705
71706
71707 public function notContains($pattern)
71708 {
71709 $this->notContains[] = $pattern;
71710
71711 return $this;
71712 }
71713
71714
71715
71716
71717
71718
71719
71720
71721
71722
71723
71724
71725
71726
71727
71728
71729
71730 public function path($pattern)
71731 {
71732 $this->paths[] = $pattern;
71733
71734 return $this;
71735 }
71736
71737
71738
71739
71740
71741
71742
71743
71744
71745
71746
71747
71748
71749
71750
71751
71752
71753 public function notPath($pattern)
71754 {
71755 $this->notPaths[] = $pattern;
71756
71757 return $this;
71758 }
71759
71760
71761
71762
71763
71764
71765
71766
71767
71768
71769
71770
71771
71772
71773
71774 public function size($size)
71775 {
71776 $this->sizes[] = new Comparator\NumberComparator($size);
71777
71778 return $this;
71779 }
71780
71781
71782
71783
71784
71785
71786
71787
71788
71789
71790
71791
71792
71793
71794 public function exclude($dirs)
71795 {
71796 $this->exclude = array_merge($this->exclude, (array) $dirs);
71797
71798 return $this;
71799 }
71800
71801
71802
71803
71804
71805
71806
71807
71808
71809
71810
71811
71812 public function ignoreDotFiles($ignoreDotFiles)
71813 {
71814 if ($ignoreDotFiles) {
71815 $this->ignore |= static::IGNORE_DOT_FILES;
71816 } else {
71817 $this->ignore &= ~static::IGNORE_DOT_FILES;
71818 }
71819
71820 return $this;
71821 }
71822
71823
71824
71825
71826
71827
71828
71829
71830
71831
71832
71833
71834 public function ignoreVCS($ignoreVCS)
71835 {
71836 if ($ignoreVCS) {
71837 $this->ignore |= static::IGNORE_VCS_FILES;
71838 } else {
71839 $this->ignore &= ~static::IGNORE_VCS_FILES;
71840 }
71841
71842 return $this;
71843 }
71844
71845
71846
71847
71848
71849
71850
71851
71852 public static function addVCSPattern($pattern)
71853 {
71854 foreach ((array) $pattern as $p) {
71855 self::$vcsPatterns[] = $p;
71856 }
71857
71858 self::$vcsPatterns = array_unique(self::$vcsPatterns);
71859 }
71860
71861
71862
71863
71864
71865
71866
71867
71868
71869
71870
71871
71872 public function sort(\Closure $closure)
71873 {
71874 $this->sort = $closure;
71875
71876 return $this;
71877 }
71878
71879
71880
71881
71882
71883
71884
71885
71886
71887
71888 public function sortByName()
71889 {
71890 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
71891
71892 return $this;
71893 }
71894
71895
71896
71897
71898
71899
71900
71901
71902
71903
71904 public function sortByType()
71905 {
71906 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
71907
71908 return $this;
71909 }
71910
71911
71912
71913
71914
71915
71916
71917
71918
71919
71920
71921
71922 public function sortByAccessedTime()
71923 {
71924 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
71925
71926 return $this;
71927 }
71928
71929
71930
71931
71932
71933
71934
71935
71936
71937
71938
71939
71940
71941
71942 public function sortByChangedTime()
71943 {
71944 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
71945
71946 return $this;
71947 }
71948
71949
71950
71951
71952
71953
71954
71955
71956
71957
71958
71959
71960 public function sortByModifiedTime()
71961 {
71962 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
71963
71964 return $this;
71965 }
71966
71967
71968
71969
71970
71971
71972
71973
71974
71975
71976
71977 public function filter(\Closure $closure)
71978 {
71979 $this->filters[] = $closure;
71980
71981 return $this;
71982 }
71983
71984
71985
71986
71987
71988
71989 public function followLinks()
71990 {
71991 $this->followLinks = true;
71992
71993 return $this;
71994 }
71995
71996
71997
71998
71999
72000
72001
72002
72003
72004
72005 public function ignoreUnreadableDirs($ignore = true)
72006 {
72007 $this->ignoreUnreadableDirs = (bool) $ignore;
72008
72009 return $this;
72010 }
72011
72012
72013
72014
72015
72016
72017
72018
72019
72020
72021 public function in($dirs)
72022 {
72023 $resolvedDirs = array();
72024
72025 foreach ((array) $dirs as $dir) {
72026 if (is_dir($dir)) {
72027 $resolvedDirs[] = $this->normalizeDir($dir);
72028 } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
72029 $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob));
72030 } else {
72031 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
72032 }
72033 }
72034
72035 $this->dirs = array_merge($this->dirs, $resolvedDirs);
72036
72037 return $this;
72038 }
72039
72040
72041
72042
72043
72044
72045
72046
72047
72048
72049 public function getIterator()
72050 {
72051 if (0 === \count($this->dirs) && 0 === \count($this->iterators)) {
72052 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
72053 }
72054
72055 if (1 === \count($this->dirs) && 0 === \count($this->iterators)) {
72056 return $this->searchInDirectory($this->dirs[0]);
72057 }
72058
72059 $iterator = new \AppendIterator();
72060 foreach ($this->dirs as $dir) {
72061 $iterator->append($this->searchInDirectory($dir));
72062 }
72063
72064 foreach ($this->iterators as $it) {
72065 $iterator->append($it);
72066 }
72067
72068 return $iterator;
72069 }
72070
72071
72072
72073
72074
72075
72076
72077
72078
72079
72080
72081
72082 public function append($iterator)
72083 {
72084 if ($iterator instanceof \IteratorAggregate) {
72085 $this->iterators[] = $iterator->getIterator();
72086 } elseif ($iterator instanceof \Iterator) {
72087 $this->iterators[] = $iterator;
72088 } elseif ($iterator instanceof \Traversable || \is_array($iterator)) {
72089 $it = new \ArrayIterator();
72090 foreach ($iterator as $file) {
72091 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
72092 }
72093 $this->iterators[] = $it;
72094 } else {
72095 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
72096 }
72097
72098 return $this;
72099 }
72100
72101
72102
72103
72104
72105
72106 public function count()
72107 {
72108 return iterator_count($this->getIterator());
72109 }
72110
72111
72112
72113
72114 private function sortAdapters()
72115 {
72116 uasort($this->adapters, function (array $a, array $b) {
72117 if ($a['selected'] || $b['selected']) {
72118 return $a['selected'] ? -1 : 1;
72119 }
72120
72121 return $a['priority'] > $b['priority'] ? -1 : 1;
72122 });
72123
72124 return $this;
72125 }
72126
72127
72128
72129
72130
72131
72132 private function searchInDirectory($dir)
72133 {
72134 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
72135 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
72136 }
72137
72138 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
72139 $this->notPaths[] = '#(^|/)\..+(/|$)#';
72140 }
72141
72142 if ($this->adapters) {
72143 foreach ($this->adapters as $adapter) {
72144 if ($adapter['adapter']->isSupported()) {
72145 try {
72146 return $this
72147 ->buildAdapter($adapter['adapter'])
72148 ->searchInDirectory($dir);
72149 } catch (ExceptionInterface $e) {
72150 }
72151 }
72152 }
72153 }
72154
72155 $minDepth = 0;
72156 $maxDepth = PHP_INT_MAX;
72157
72158 foreach ($this->depths as $comparator) {
72159 switch ($comparator->getOperator()) {
72160 case '>':
72161 $minDepth = $comparator->getTarget() + 1;
72162 break;
72163 case '>=':
72164 $minDepth = $comparator->getTarget();
72165 break;
72166 case '<':
72167 $maxDepth = $comparator->getTarget() - 1;
72168 break;
72169 case '<=':
72170 $maxDepth = $comparator->getTarget();
72171 break;
72172 default:
72173 $minDepth = $maxDepth = $comparator->getTarget();
72174 }
72175 }
72176
72177 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
72178
72179 if ($this->followLinks) {
72180 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
72181 }
72182
72183 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
72184
72185 if ($this->exclude) {
72186 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
72187 }
72188
72189 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
72190
72191 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
72192 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
72193 }
72194
72195 if ($this->mode) {
72196 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
72197 }
72198
72199 if ($this->names || $this->notNames) {
72200 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
72201 }
72202
72203 if ($this->contains || $this->notContains) {
72204 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
72205 }
72206
72207 if ($this->sizes) {
72208 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
72209 }
72210
72211 if ($this->dates) {
72212 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
72213 }
72214
72215 if ($this->filters) {
72216 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
72217 }
72218
72219 if ($this->paths || $this->notPaths) {
72220 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
72221 }
72222
72223 if ($this->sort) {
72224 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
72225 $iterator = $iteratorAggregate->getIterator();
72226 }
72227
72228 return $iterator;
72229 }
72230
72231
72232
72233
72234 private function buildAdapter(AdapterInterface $adapter)
72235 {
72236 return $adapter
72237 ->setFollowLinks($this->followLinks)
72238 ->setDepths($this->depths)
72239 ->setMode($this->mode)
72240 ->setExclude($this->exclude)
72241 ->setNames($this->names)
72242 ->setNotNames($this->notNames)
72243 ->setContains($this->contains)
72244 ->setNotContains($this->notContains)
72245 ->setSizes($this->sizes)
72246 ->setDates($this->dates)
72247 ->setFilters($this->filters)
72248 ->setSort($this->sort)
72249 ->setPath($this->paths)
72250 ->setNotPath($this->notPaths)
72251 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
72252 }
72253
72254
72255
72256
72257 private function resetAdapterSelection()
72258 {
72259 $this->adapters = array_map(function (array $properties) {
72260 $properties['selected'] = false;
72261
72262 return $properties;
72263 }, $this->adapters);
72264 }
72265
72266 private function initDefaultAdapters()
72267 {
72268 if (null === $this->adapters) {
72269 $this->adapters = array();
72270 $this
72271 ->addAdapter(new GnuFindAdapter())
72272 ->addAdapter(new BsdFindAdapter())
72273 ->addAdapter(new PhpAdapter(), -50)
72274 ->setAdapter('php')
72275 ;
72276 }
72277 }
72278
72279
72280
72281
72282
72283
72284
72285
72286 private function normalizeDir($dir)
72287 {
72288 return rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
72289 }
72290 }
72291 <?php
72292
72293
72294
72295
72296
72297
72298
72299
72300
72301
72302 namespace Symfony\Component\Finder;
72303
72304
72305
72306
72307
72308
72309
72310
72311
72312
72313
72314
72315
72316
72317
72318
72319
72320
72321
72322
72323
72324
72325
72326 class Glob
72327 {
72328
72329
72330
72331
72332
72333
72334
72335
72336
72337
72338 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
72339 {
72340 $firstByte = true;
72341 $escaping = false;
72342 $inCurlies = 0;
72343 $regex = '';
72344 $sizeGlob = \strlen($glob);
72345 for ($i = 0; $i < $sizeGlob; ++$i) {
72346 $car = $glob[$i];
72347 if ($firstByte) {
72348 if ($strictLeadingDot && '.' !== $car) {
72349 $regex .= '(?=[^\.])';
72350 }
72351
72352 $firstByte = false;
72353 }
72354
72355 if ('/' === $car) {
72356 $firstByte = true;
72357 }
72358
72359 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
72360 $regex .= "\\$car";
72361 } elseif ('*' === $car) {
72362 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
72363 } elseif ('?' === $car) {
72364 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
72365 } elseif ('{' === $car) {
72366 $regex .= $escaping ? '\\{' : '(';
72367 if (!$escaping) {
72368 ++$inCurlies;
72369 }
72370 } elseif ('}' === $car && $inCurlies) {
72371 $regex .= $escaping ? '}' : ')';
72372 if (!$escaping) {
72373 --$inCurlies;
72374 }
72375 } elseif (',' === $car && $inCurlies) {
72376 $regex .= $escaping ? ',' : '|';
72377 } elseif ('\\' === $car) {
72378 if ($escaping) {
72379 $regex .= '\\\\';
72380 $escaping = false;
72381 } else {
72382 $escaping = true;
72383 }
72384
72385 continue;
72386 } else {
72387 $regex .= $car;
72388 }
72389 $escaping = false;
72390 }
72391
72392 return $delimiter.'^'.$regex.'$'.$delimiter;
72393 }
72394 }
72395 <?php
72396
72397
72398
72399
72400
72401
72402
72403
72404
72405
72406 namespace Symfony\Component\Finder\Iterator;
72407
72408
72409
72410
72411
72412
72413
72414
72415
72416 class CustomFilterIterator extends FilterIterator
72417 {
72418 private $filters = array();
72419
72420
72421
72422
72423
72424
72425
72426 public function __construct(\Iterator $iterator, array $filters)
72427 {
72428 foreach ($filters as $filter) {
72429 if (!\is_callable($filter)) {
72430 throw new \InvalidArgumentException('Invalid PHP callback.');
72431 }
72432 }
72433 $this->filters = $filters;
72434
72435 parent::__construct($iterator);
72436 }
72437
72438
72439
72440
72441
72442
72443 public function accept()
72444 {
72445 $fileinfo = $this->current();
72446
72447 foreach ($this->filters as $filter) {
72448 if (false === \call_user_func($filter, $fileinfo)) {
72449 return false;
72450 }
72451 }
72452
72453 return true;
72454 }
72455 }
72456 <?php
72457
72458
72459
72460
72461
72462
72463
72464
72465
72466
72467 namespace Symfony\Component\Finder\Iterator;
72468
72469 use Symfony\Component\Finder\Comparator\DateComparator;
72470
72471
72472
72473
72474
72475
72476 class DateRangeFilterIterator extends FilterIterator
72477 {
72478 private $comparators = array();
72479
72480
72481
72482
72483
72484 public function __construct(\Iterator $iterator, array $comparators)
72485 {
72486 $this->comparators = $comparators;
72487
72488 parent::__construct($iterator);
72489 }
72490
72491
72492
72493
72494
72495
72496 public function accept()
72497 {
72498 $fileinfo = $this->current();
72499
72500 if (!file_exists($fileinfo->getPathname())) {
72501 return false;
72502 }
72503
72504 $filedate = $fileinfo->getMTime();
72505 foreach ($this->comparators as $compare) {
72506 if (!$compare->test($filedate)) {
72507 return false;
72508 }
72509 }
72510
72511 return true;
72512 }
72513 }
72514 <?php
72515
72516
72517
72518
72519
72520
72521
72522
72523
72524
72525 namespace Symfony\Component\Finder\Iterator;
72526
72527
72528
72529
72530
72531
72532 class DepthRangeFilterIterator extends FilterIterator
72533 {
72534 private $minDepth = 0;
72535
72536
72537
72538
72539
72540
72541 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
72542 {
72543 $this->minDepth = $minDepth;
72544 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
72545
72546 parent::__construct($iterator);
72547 }
72548
72549
72550
72551
72552
72553
72554 public function accept()
72555 {
72556 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
72557 }
72558 }
72559 <?php
72560
72561
72562
72563
72564
72565
72566
72567
72568
72569
72570 namespace Symfony\Component\Finder\Iterator;
72571
72572
72573
72574
72575
72576
72577 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
72578 {
72579 private $iterator;
72580 private $isRecursive;
72581 private $excludedDirs = array();
72582 private $excludedPattern;
72583
72584
72585
72586
72587
72588 public function __construct(\Iterator $iterator, array $directories)
72589 {
72590 $this->iterator = $iterator;
72591 $this->isRecursive = $iterator instanceof \RecursiveIterator;
72592 $patterns = array();
72593 foreach ($directories as $directory) {
72594 $directory = rtrim($directory, '/');
72595 if (!$this->isRecursive || false !== strpos($directory, '/')) {
72596 $patterns[] = preg_quote($directory, '#');
72597 } else {
72598 $this->excludedDirs[$directory] = true;
72599 }
72600 }
72601 if ($patterns) {
72602 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
72603 }
72604
72605 parent::__construct($iterator);
72606 }
72607
72608
72609
72610
72611
72612
72613 public function accept()
72614 {
72615 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
72616 return false;
72617 }
72618
72619 if ($this->excludedPattern) {
72620 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
72621 $path = str_replace('\\', '/', $path);
72622
72623 return !preg_match($this->excludedPattern, $path);
72624 }
72625
72626 return true;
72627 }
72628
72629 public function hasChildren()
72630 {
72631 return $this->isRecursive && $this->iterator->hasChildren();
72632 }
72633
72634 public function getChildren()
72635 {
72636 $children = new self($this->iterator->getChildren(), array());
72637 $children->excludedDirs = $this->excludedDirs;
72638 $children->excludedPattern = $this->excludedPattern;
72639
72640 return $children;
72641 }
72642 }
72643 <?php
72644
72645
72646
72647
72648
72649
72650
72651
72652
72653
72654 namespace Symfony\Component\Finder\Iterator;
72655
72656 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
72657
72658 use Symfony\Component\Finder\SplFileInfo;
72659
72660
72661
72662
72663
72664
72665
72666
72667 class FilePathsIterator extends \ArrayIterator
72668 {
72669
72670
72671
72672 private $baseDir;
72673
72674
72675
72676
72677 private $baseDirLength;
72678
72679
72680
72681
72682 private $subPath;
72683
72684
72685
72686
72687 private $subPathname;
72688
72689
72690
72691
72692 private $current;
72693
72694
72695
72696
72697
72698 public function __construct(array $paths, $baseDir)
72699 {
72700 $this->baseDir = $baseDir;
72701 $this->baseDirLength = \strlen($baseDir);
72702
72703 parent::__construct($paths);
72704 }
72705
72706
72707
72708
72709
72710
72711
72712 public function __call($name, array $arguments)
72713 {
72714 return \call_user_func_array(array($this->current(), $name), $arguments);
72715 }
72716
72717
72718
72719
72720
72721
72722 public function current()
72723 {
72724 return $this->current;
72725 }
72726
72727
72728
72729
72730 public function key()
72731 {
72732 return $this->current->getPathname();
72733 }
72734
72735 public function next()
72736 {
72737 parent::next();
72738 $this->buildProperties();
72739 }
72740
72741 public function rewind()
72742 {
72743 parent::rewind();
72744 $this->buildProperties();
72745 }
72746
72747
72748
72749
72750 public function getSubPath()
72751 {
72752 return $this->subPath;
72753 }
72754
72755
72756
72757
72758 public function getSubPathname()
72759 {
72760 return $this->subPathname;
72761 }
72762
72763 private function buildProperties()
72764 {
72765 $absolutePath = parent::current();
72766
72767 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
72768 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
72769 $dir = \dirname($this->subPathname);
72770 $this->subPath = '.' === $dir ? '' : $dir;
72771 } else {
72772 $this->subPath = $this->subPathname = '';
72773 }
72774
72775 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
72776 }
72777 }
72778 <?php
72779
72780
72781
72782
72783
72784
72785
72786
72787
72788
72789 namespace Symfony\Component\Finder\Iterator;
72790
72791
72792
72793
72794
72795
72796 class FileTypeFilterIterator extends FilterIterator
72797 {
72798 const ONLY_FILES = 1;
72799 const ONLY_DIRECTORIES = 2;
72800
72801 private $mode;
72802
72803
72804
72805
72806
72807 public function __construct(\Iterator $iterator, $mode)
72808 {
72809 $this->mode = $mode;
72810
72811 parent::__construct($iterator);
72812 }
72813
72814
72815
72816
72817
72818
72819 public function accept()
72820 {
72821 $fileinfo = $this->current();
72822 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
72823 return false;
72824 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
72825 return false;
72826 }
72827
72828 return true;
72829 }
72830 }
72831 <?php
72832
72833
72834
72835
72836
72837
72838
72839
72840
72841
72842 namespace Symfony\Component\Finder\Iterator;
72843
72844
72845
72846
72847
72848
72849
72850 class FilecontentFilterIterator extends MultiplePcreFilterIterator
72851 {
72852
72853
72854
72855
72856
72857 public function accept()
72858 {
72859 if (!$this->matchRegexps && !$this->noMatchRegexps) {
72860 return true;
72861 }
72862
72863 $fileinfo = $this->current();
72864
72865 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
72866 return false;
72867 }
72868
72869 $content = $fileinfo->getContents();
72870 if (!$content) {
72871 return false;
72872 }
72873
72874 return $this->isAccepted($content);
72875 }
72876
72877
72878
72879
72880
72881
72882
72883
72884 protected function toRegex($str)
72885 {
72886 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
72887 }
72888 }
72889 <?php
72890
72891
72892
72893
72894
72895
72896
72897
72898
72899
72900 namespace Symfony\Component\Finder\Iterator;
72901
72902 use Symfony\Component\Finder\Glob;
72903
72904
72905
72906
72907
72908
72909 class FilenameFilterIterator extends MultiplePcreFilterIterator
72910 {
72911
72912
72913
72914
72915
72916 public function accept()
72917 {
72918 return $this->isAccepted($this->current()->getFilename());
72919 }
72920
72921
72922
72923
72924
72925
72926
72927
72928
72929
72930
72931 protected function toRegex($str)
72932 {
72933 return $this->isRegex($str) ? $str : Glob::toRegex($str);
72934 }
72935 }
72936 <?php
72937
72938
72939
72940
72941
72942
72943
72944
72945
72946
72947 namespace Symfony\Component\Finder\Iterator;
72948
72949
72950
72951
72952
72953
72954
72955
72956
72957 abstract class FilterIterator extends \FilterIterator
72958 {
72959
72960
72961
72962
72963
72964
72965 public function rewind()
72966 {
72967 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
72968 parent::rewind();
72969
72970 return;
72971 }
72972
72973 $iterator = $this;
72974 while ($iterator instanceof \OuterIterator) {
72975 $innerIterator = $iterator->getInnerIterator();
72976
72977 if ($innerIterator instanceof RecursiveDirectoryIterator) {
72978
72979 if ($innerIterator->isRewindable()) {
72980 $innerIterator->next();
72981 $innerIterator->rewind();
72982 }
72983 } elseif ($innerIterator instanceof \FilesystemIterator) {
72984 $innerIterator->next();
72985 $innerIterator->rewind();
72986 }
72987
72988 $iterator = $innerIterator;
72989 }
72990
72991 parent::rewind();
72992 }
72993 }
72994 <?php
72995
72996
72997
72998
72999
73000
73001
73002
73003
73004
73005 namespace Symfony\Component\Finder\Iterator;
73006
73007
73008
73009
73010
73011
73012 abstract class MultiplePcreFilterIterator extends FilterIterator
73013 {
73014 protected $matchRegexps = array();
73015 protected $noMatchRegexps = array();
73016
73017
73018
73019
73020
73021
73022 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
73023 {
73024 foreach ($matchPatterns as $pattern) {
73025 $this->matchRegexps[] = $this->toRegex($pattern);
73026 }
73027
73028 foreach ($noMatchPatterns as $pattern) {
73029 $this->noMatchRegexps[] = $this->toRegex($pattern);
73030 }
73031
73032 parent::__construct($iterator);
73033 }
73034
73035
73036
73037
73038
73039
73040
73041
73042
73043
73044
73045
73046 protected function isAccepted($string)
73047 {
73048
73049 foreach ($this->noMatchRegexps as $regex) {
73050 if (preg_match($regex, $string)) {
73051 return false;
73052 }
73053 }
73054
73055
73056 if ($this->matchRegexps) {
73057 foreach ($this->matchRegexps as $regex) {
73058 if (preg_match($regex, $string)) {
73059 return true;
73060 }
73061 }
73062
73063 return false;
73064 }
73065
73066
73067 return true;
73068 }
73069
73070
73071
73072
73073
73074
73075
73076
73077 protected function isRegex($str)
73078 {
73079 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
73080 $start = substr($m[1], 0, 1);
73081 $end = substr($m[1], -1);
73082
73083 if ($start === $end) {
73084 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
73085 }
73086
73087 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
73088 if ($start === $delimiters[0] && $end === $delimiters[1]) {
73089 return true;
73090 }
73091 }
73092 }
73093
73094 return false;
73095 }
73096
73097
73098
73099
73100
73101
73102
73103
73104 abstract protected function toRegex($str);
73105 }
73106 <?php
73107
73108
73109
73110
73111
73112
73113
73114
73115
73116
73117 namespace Symfony\Component\Finder\Iterator;
73118
73119
73120
73121
73122
73123
73124
73125 class PathFilterIterator extends MultiplePcreFilterIterator
73126 {
73127
73128
73129
73130
73131
73132 public function accept()
73133 {
73134 $filename = $this->current()->getRelativePathname();
73135
73136 if ('\\' === \DIRECTORY_SEPARATOR) {
73137 $filename = str_replace('\\', '/', $filename);
73138 }
73139
73140 return $this->isAccepted($filename);
73141 }
73142
73143
73144
73145
73146
73147
73148
73149
73150
73151
73152
73153
73154
73155
73156
73157 protected function toRegex($str)
73158 {
73159 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
73160 }
73161 }
73162 <?php
73163
73164
73165
73166
73167
73168
73169
73170
73171
73172
73173 namespace Symfony\Component\Finder\Iterator;
73174
73175 use Symfony\Component\Finder\Exception\AccessDeniedException;
73176 use Symfony\Component\Finder\SplFileInfo;
73177
73178
73179
73180
73181
73182
73183 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
73184 {
73185
73186
73187
73188 private $ignoreUnreadableDirs;
73189
73190
73191
73192
73193 private $rewindable;
73194
73195
73196 private $rootPath;
73197 private $subPath;
73198 private $directorySeparator = '/';
73199
73200
73201
73202
73203
73204
73205
73206
73207 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
73208 {
73209 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
73210 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
73211 }
73212
73213 parent::__construct($path, $flags);
73214 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
73215 $this->rootPath = (string) $path;
73216 if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
73217 $this->directorySeparator = \DIRECTORY_SEPARATOR;
73218 }
73219 }
73220
73221
73222
73223
73224
73225
73226 public function current()
73227 {
73228
73229
73230 if (null === $subPathname = $this->subPath) {
73231 $subPathname = $this->subPath = (string) $this->getSubPath();
73232 }
73233 if ('' !== $subPathname) {
73234 $subPathname .= $this->directorySeparator;
73235 }
73236 $subPathname .= $this->getFilename();
73237
73238 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
73239 }
73240
73241
73242
73243
73244
73245
73246 public function getChildren()
73247 {
73248 try {
73249 $children = parent::getChildren();
73250
73251 if ($children instanceof self) {
73252
73253 $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
73254
73255
73256 $children->rewindable = &$this->rewindable;
73257 $children->rootPath = $this->rootPath;
73258 }
73259
73260 return $children;
73261 } catch (\UnexpectedValueException $e) {
73262 if ($this->ignoreUnreadableDirs) {
73263
73264 return new \RecursiveArrayIterator(array());
73265 } else {
73266 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
73267 }
73268 }
73269 }
73270
73271
73272
73273
73274 public function rewind()
73275 {
73276 if (false === $this->isRewindable()) {
73277 return;
73278 }
73279
73280
73281 if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
73282 parent::next();
73283 }
73284
73285 parent::rewind();
73286 }
73287
73288
73289
73290
73291
73292
73293 public function isRewindable()
73294 {
73295 if (null !== $this->rewindable) {
73296 return $this->rewindable;
73297 }
73298
73299
73300 if ('' === $this->getPath()) {
73301 return $this->rewindable = false;
73302 }
73303
73304 if (false !== $stream = @opendir($this->getPath())) {
73305 $infos = stream_get_meta_data($stream);
73306 closedir($stream);
73307
73308 if ($infos['seekable']) {
73309 return $this->rewindable = true;
73310 }
73311 }
73312
73313 return $this->rewindable = false;
73314 }
73315 }
73316 <?php
73317
73318
73319
73320
73321
73322
73323
73324
73325
73326
73327 namespace Symfony\Component\Finder\Iterator;
73328
73329 use Symfony\Component\Finder\Comparator\NumberComparator;
73330
73331
73332
73333
73334
73335
73336 class SizeRangeFilterIterator extends FilterIterator
73337 {
73338 private $comparators = array();
73339
73340
73341
73342
73343
73344 public function __construct(\Iterator $iterator, array $comparators)
73345 {
73346 $this->comparators = $comparators;
73347
73348 parent::__construct($iterator);
73349 }
73350
73351
73352
73353
73354
73355
73356 public function accept()
73357 {
73358 $fileinfo = $this->current();
73359 if (!$fileinfo->isFile()) {
73360 return true;
73361 }
73362
73363 $filesize = $fileinfo->getSize();
73364 foreach ($this->comparators as $compare) {
73365 if (!$compare->test($filesize)) {
73366 return false;
73367 }
73368 }
73369
73370 return true;
73371 }
73372 }
73373 <?php
73374
73375
73376
73377
73378
73379
73380
73381
73382
73383
73384 namespace Symfony\Component\Finder\Iterator;
73385
73386
73387
73388
73389
73390
73391 class SortableIterator implements \IteratorAggregate
73392 {
73393 const SORT_BY_NAME = 1;
73394 const SORT_BY_TYPE = 2;
73395 const SORT_BY_ACCESSED_TIME = 3;
73396 const SORT_BY_CHANGED_TIME = 4;
73397 const SORT_BY_MODIFIED_TIME = 5;
73398
73399 private $iterator;
73400 private $sort;
73401
73402
73403
73404
73405
73406
73407
73408 public function __construct(\Traversable $iterator, $sort)
73409 {
73410 $this->iterator = $iterator;
73411
73412 if (self::SORT_BY_NAME === $sort) {
73413 $this->sort = function ($a, $b) {
73414 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
73415 };
73416 } elseif (self::SORT_BY_TYPE === $sort) {
73417 $this->sort = function ($a, $b) {
73418 if ($a->isDir() && $b->isFile()) {
73419 return -1;
73420 } elseif ($a->isFile() && $b->isDir()) {
73421 return 1;
73422 }
73423
73424 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
73425 };
73426 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
73427 $this->sort = function ($a, $b) {
73428 return $a->getATime() - $b->getATime();
73429 };
73430 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
73431 $this->sort = function ($a, $b) {
73432 return $a->getCTime() - $b->getCTime();
73433 };
73434 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
73435 $this->sort = function ($a, $b) {
73436 return $a->getMTime() - $b->getMTime();
73437 };
73438 } elseif (\is_callable($sort)) {
73439 $this->sort = $sort;
73440 } else {
73441 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
73442 }
73443 }
73444
73445 public function getIterator()
73446 {
73447 $array = iterator_to_array($this->iterator, true);
73448 uasort($array, $this->sort);
73449
73450 return new \ArrayIterator($array);
73451 }
73452 }
73453 Copyright (c) 2004-2018 Fabien Potencier
73454
73455 Permission is hereby granted, free of charge, to any person obtaining a copy
73456 of this software and associated documentation files (the "Software"), to deal
73457 in the Software without restriction, including without limitation the rights
73458 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
73459 copies of the Software, and to permit persons to whom the Software is furnished
73460 to do so, subject to the following conditions:
73461
73462 The above copyright notice and this permission notice shall be included in all
73463 copies or substantial portions of the Software.
73464
73465 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73466 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
73467 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73468 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73469 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
73470 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
73471 THE SOFTWARE.
73472 <?php
73473
73474
73475
73476
73477
73478
73479
73480
73481
73482
73483 namespace Symfony\Component\Finder\Shell;
73484
73485 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
73486
73487
73488
73489
73490
73491
73492 class Command
73493 {
73494 private $parent;
73495 private $bits = array();
73496 private $labels = array();
73497
73498
73499
73500
73501 private $errorHandler;
73502
73503 public function __construct(Command $parent = null)
73504 {
73505 $this->parent = $parent;
73506 }
73507
73508
73509
73510
73511
73512
73513 public function __toString()
73514 {
73515 return $this->join();
73516 }
73517
73518
73519
73520
73521
73522
73523 public static function create(Command $parent = null)
73524 {
73525 return new self($parent);
73526 }
73527
73528
73529
73530
73531
73532
73533
73534
73535 public static function escape($input)
73536 {
73537 return escapeshellcmd($input);
73538 }
73539
73540
73541
73542
73543
73544
73545
73546
73547 public static function quote($input)
73548 {
73549 return escapeshellarg($input);
73550 }
73551
73552
73553
73554
73555
73556
73557
73558
73559 public function add($bit)
73560 {
73561 $this->bits[] = $bit;
73562
73563 return $this;
73564 }
73565
73566
73567
73568
73569
73570
73571
73572
73573 public function top($bit)
73574 {
73575 array_unshift($this->bits, $bit);
73576
73577 foreach ($this->labels as $label => $index) {
73578 ++$this->labels[$label];
73579 }
73580
73581 return $this;
73582 }
73583
73584
73585
73586
73587
73588
73589
73590
73591 public function arg($arg)
73592 {
73593 $this->bits[] = self::quote($arg);
73594
73595 return $this;
73596 }
73597
73598
73599
73600
73601
73602
73603
73604
73605 public function cmd($esc)
73606 {
73607 $this->bits[] = self::escape($esc);
73608
73609 return $this;
73610 }
73611
73612
73613
73614
73615
73616
73617
73618
73619
73620
73621 public function ins($label)
73622 {
73623 if (isset($this->labels[$label])) {
73624 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
73625 }
73626
73627 $this->bits[] = self::create($this);
73628 $this->labels[$label] = \count($this->bits) - 1;
73629
73630 return $this->bits[$this->labels[$label]];
73631 }
73632
73633
73634
73635
73636
73637
73638
73639
73640
73641
73642 public function get($label)
73643 {
73644 if (!isset($this->labels[$label])) {
73645 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
73646 }
73647
73648 return $this->bits[$this->labels[$label]];
73649 }
73650
73651
73652
73653
73654
73655
73656
73657
73658 public function end()
73659 {
73660 if (null === $this->parent) {
73661 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
73662 }
73663
73664 return $this->parent;
73665 }
73666
73667
73668
73669
73670
73671
73672 public function length()
73673 {
73674 return \count($this->bits);
73675 }
73676
73677
73678
73679
73680 public function setErrorHandler(\Closure $errorHandler)
73681 {
73682 $this->errorHandler = $errorHandler;
73683
73684 return $this;
73685 }
73686
73687
73688
73689
73690 public function getErrorHandler()
73691 {
73692 return $this->errorHandler;
73693 }
73694
73695
73696
73697
73698
73699
73700
73701
73702 public function execute()
73703 {
73704 if (null === $errorHandler = $this->errorHandler) {
73705 exec($this->join(), $output);
73706 } else {
73707 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
73708 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
73709
73710 if ($error = stream_get_contents($pipes[2])) {
73711 $errorHandler($error);
73712 }
73713
73714 proc_close($process);
73715 }
73716
73717 return $output ?: array();
73718 }
73719
73720
73721
73722
73723
73724
73725 public function join()
73726 {
73727 return implode(' ', array_filter(
73728 array_map(function ($bit) {
73729 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
73730 }, $this->bits),
73731 function ($bit) { return null !== $bit; }
73732 ));
73733 }
73734
73735
73736
73737
73738
73739
73740
73741
73742
73743 public function addAtIndex($bit, $index)
73744 {
73745 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
73746
73747 return $this;
73748 }
73749 }
73750 <?php
73751
73752
73753
73754
73755
73756
73757
73758
73759
73760
73761 namespace Symfony\Component\Finder\Shell;
73762
73763 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
73764
73765
73766
73767
73768
73769
73770 class Shell
73771 {
73772 const TYPE_UNIX = 1;
73773 const TYPE_DARWIN = 2;
73774 const TYPE_CYGWIN = 3;
73775 const TYPE_WINDOWS = 4;
73776 const TYPE_BSD = 5;
73777
73778
73779
73780
73781 private $type;
73782
73783
73784
73785
73786
73787
73788 public function getType()
73789 {
73790 if (null === $this->type) {
73791 $this->type = $this->guessType();
73792 }
73793
73794 return $this->type;
73795 }
73796
73797
73798
73799
73800
73801
73802
73803
73804 public function testCommand($command)
73805 {
73806 if (!\function_exists('exec')) {
73807 return false;
73808 }
73809
73810
73811 $testCommand = 'which ';
73812 if (self::TYPE_WINDOWS === $this->type) {
73813 $testCommand = 'where ';
73814 }
73815
73816 $command = escapeshellcmd($command);
73817
73818 exec($testCommand.$command, $output, $code);
73819
73820 return 0 === $code && \count($output) > 0;
73821 }
73822
73823
73824
73825
73826
73827
73828 private function guessType()
73829 {
73830 $os = strtolower(PHP_OS);
73831
73832 if (false !== strpos($os, 'cygwin')) {
73833 return self::TYPE_CYGWIN;
73834 }
73835
73836 if (false !== strpos($os, 'darwin')) {
73837 return self::TYPE_DARWIN;
73838 }
73839
73840 if (false !== strpos($os, 'bsd')) {
73841 return self::TYPE_BSD;
73842 }
73843
73844 if (0 === strpos($os, 'win')) {
73845 return self::TYPE_WINDOWS;
73846 }
73847
73848 return self::TYPE_UNIX;
73849 }
73850 }
73851 <?php
73852
73853
73854
73855
73856
73857
73858
73859
73860
73861
73862 namespace Symfony\Component\Finder;
73863
73864
73865
73866
73867
73868
73869 class SplFileInfo extends \SplFileInfo
73870 {
73871 private $relativePath;
73872 private $relativePathname;
73873
73874
73875
73876
73877
73878
73879 public function __construct($file, $relativePath, $relativePathname)
73880 {
73881 parent::__construct($file);
73882 $this->relativePath = $relativePath;
73883 $this->relativePathname = $relativePathname;
73884 }
73885
73886
73887
73888
73889
73890
73891
73892
73893 public function getRelativePath()
73894 {
73895 return $this->relativePath;
73896 }
73897
73898
73899
73900
73901
73902
73903
73904
73905 public function getRelativePathname()
73906 {
73907 return $this->relativePathname;
73908 }
73909
73910
73911
73912
73913
73914
73915
73916
73917 public function getContents()
73918 {
73919 set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
73920 $content = file_get_contents($this->getPathname());
73921 restore_error_handler();
73922 if (false === $content) {
73923 throw new \RuntimeException($error);
73924 }
73925
73926 return $content;
73927 }
73928 }
73929 <?php
73930
73931
73932
73933
73934
73935
73936
73937
73938
73939
73940 namespace Symfony\Polyfill\Ctype;
73941
73942
73943
73944
73945
73946
73947
73948
73949 final class Ctype
73950 {
73951
73952
73953
73954
73955
73956
73957
73958
73959
73960 public static function ctype_alnum($text)
73961 {
73962 $text = self::convert_int_to_char_for_ctype($text);
73963
73964 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
73965 }
73966
73967
73968
73969
73970
73971
73972
73973
73974
73975
73976 public static function ctype_alpha($text)
73977 {
73978 $text = self::convert_int_to_char_for_ctype($text);
73979
73980 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
73981 }
73982
73983
73984
73985
73986
73987
73988
73989
73990
73991
73992 public static function ctype_cntrl($text)
73993 {
73994 $text = self::convert_int_to_char_for_ctype($text);
73995
73996 return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
73997 }
73998
73999
74000
74001
74002
74003
74004
74005
74006
74007
74008 public static function ctype_digit($text)
74009 {
74010 $text = self::convert_int_to_char_for_ctype($text);
74011
74012 return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
74013 }
74014
74015
74016
74017
74018
74019
74020
74021
74022
74023
74024 public static function ctype_graph($text)
74025 {
74026 $text = self::convert_int_to_char_for_ctype($text);
74027
74028 return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
74029 }
74030
74031
74032
74033
74034
74035
74036
74037
74038
74039
74040 public static function ctype_lower($text)
74041 {
74042 $text = self::convert_int_to_char_for_ctype($text);
74043
74044 return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
74045 }
74046
74047
74048
74049
74050
74051
74052
74053
74054
74055
74056 public static function ctype_print($text)
74057 {
74058 $text = self::convert_int_to_char_for_ctype($text);
74059
74060 return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
74061 }
74062
74063
74064
74065
74066
74067
74068
74069
74070
74071
74072 public static function ctype_punct($text)
74073 {
74074 $text = self::convert_int_to_char_for_ctype($text);
74075
74076 return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
74077 }
74078
74079
74080
74081
74082
74083
74084
74085
74086
74087
74088 public static function ctype_space($text)
74089 {
74090 $text = self::convert_int_to_char_for_ctype($text);
74091
74092 return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
74093 }
74094
74095
74096
74097
74098
74099
74100
74101
74102
74103
74104 public static function ctype_upper($text)
74105 {
74106 $text = self::convert_int_to_char_for_ctype($text);
74107
74108 return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
74109 }
74110
74111
74112
74113
74114
74115
74116
74117
74118
74119
74120 public static function ctype_xdigit($text)
74121 {
74122 $text = self::convert_int_to_char_for_ctype($text);
74123
74124 return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
74125 }
74126
74127
74128
74129
74130
74131
74132
74133
74134
74135
74136
74137
74138
74139 private static function convert_int_to_char_for_ctype($int)
74140 {
74141 if (!\is_int($int)) {
74142 return $int;
74143 }
74144
74145 if ($int < -128 || $int > 255) {
74146 return (string) $int;
74147 }
74148
74149 if ($int < 0) {
74150 $int += 256;
74151 }
74152
74153 return \chr($int);
74154 }
74155 }
74156 Copyright (c) 2018-2019 Fabien Potencier
74157
74158 Permission is hereby granted, free of charge, to any person obtaining a copy
74159 of this software and associated documentation files (the "Software"), to deal
74160 in the Software without restriction, including without limitation the rights
74161 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
74162 copies of the Software, and to permit persons to whom the Software is furnished
74163 to do so, subject to the following conditions:
74164
74165 The above copyright notice and this permission notice shall be included in all
74166 copies or substantial portions of the Software.
74167
74168 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74169 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74170 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74171 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74172 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74173 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
74174 THE SOFTWARE.
74175 <?php
74176
74177
74178
74179
74180
74181
74182
74183
74184
74185
74186 use Symfony\Polyfill\Ctype as p;
74187
74188 if (!function_exists('ctype_alnum')) {
74189 function ctype_alnum($input) { return p\Ctype::ctype_alnum($input); }
74190 }
74191 if (!function_exists('ctype_alpha')) {
74192 function ctype_alpha($input) { return p\Ctype::ctype_alpha($input); }
74193 }
74194 if (!function_exists('ctype_cntrl')) {
74195 function ctype_cntrl($input) { return p\Ctype::ctype_cntrl($input); }
74196 }
74197 if (!function_exists('ctype_digit')) {
74198 function ctype_digit($input) { return p\Ctype::ctype_digit($input); }
74199 }
74200 if (!function_exists('ctype_graph')) {
74201 function ctype_graph($input) { return p\Ctype::ctype_graph($input); }
74202 }
74203 if (!function_exists('ctype_lower')) {
74204 function ctype_lower($input) { return p\Ctype::ctype_lower($input); }
74205 }
74206 if (!function_exists('ctype_print')) {
74207 function ctype_print($input) { return p\Ctype::ctype_print($input); }
74208 }
74209 if (!function_exists('ctype_punct')) {
74210 function ctype_punct($input) { return p\Ctype::ctype_punct($input); }
74211 }
74212 if (!function_exists('ctype_space')) {
74213 function ctype_space($input) { return p\Ctype::ctype_space($input); }
74214 }
74215 if (!function_exists('ctype_upper')) {
74216 function ctype_upper($input) { return p\Ctype::ctype_upper($input); }
74217 }
74218 if (!function_exists('ctype_xdigit')) {
74219 function ctype_xdigit($input) { return p\Ctype::ctype_xdigit($input); }
74220 }
74221 Copyright (c) 2015-2019 Fabien Potencier
74222
74223 Permission is hereby granted, free of charge, to any person obtaining a copy
74224 of this software and associated documentation files (the "Software"), to deal
74225 in the Software without restriction, including without limitation the rights
74226 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
74227 copies of the Software, and to permit persons to whom the Software is furnished
74228 to do so, subject to the following conditions:
74229
74230 The above copyright notice and this permission notice shall be included in all
74231 copies or substantial portions of the Software.
74232
74233 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74234 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74235 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74236 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74237 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74238 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
74239 THE SOFTWARE.
74240 <?php
74241
74242
74243
74244
74245
74246
74247
74248
74249
74250
74251 namespace Symfony\Polyfill\Mbstring;
74252
74253
74254
74255
74256
74257
74258
74259
74260
74261
74262
74263
74264
74265
74266
74267
74268
74269
74270
74271
74272
74273
74274
74275
74276
74277
74278
74279
74280
74281
74282
74283
74284
74285
74286
74287
74288
74289
74290
74291
74292
74293
74294
74295
74296
74297
74298
74299
74300
74301
74302
74303
74304
74305
74306
74307 final class Mbstring
74308 {
74309 const MB_CASE_FOLD = PHP_INT_MAX;
74310
74311 private static $encodingList = array('ASCII', 'UTF-8');
74312 private static $language = 'neutral';
74313 private static $internalEncoding = 'UTF-8';
74314 private static $caseFold = array(
74315 array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"),
74316 array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'),
74317 );
74318
74319 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
74320 {
74321 if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
74322 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
74323 } else {
74324 $fromEncoding = self::getEncoding($fromEncoding);
74325 }
74326
74327 $toEncoding = self::getEncoding($toEncoding);
74328
74329 if ('BASE64' === $fromEncoding) {
74330 $s = base64_decode($s);
74331 $fromEncoding = $toEncoding;
74332 }
74333
74334 if ('BASE64' === $toEncoding) {
74335 return base64_encode($s);
74336 }
74337
74338 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
74339 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
74340 $fromEncoding = 'Windows-1252';
74341 }
74342 if ('UTF-8' !== $fromEncoding) {
74343 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
74344 }
74345
74346 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
74347 }
74348
74349 if ('HTML-ENTITIES' === $fromEncoding) {
74350 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
74351 $fromEncoding = 'UTF-8';
74352 }
74353
74354 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
74355 }
74356
74357 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
74358 {
74359 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
74360
74361 $ok = true;
74362 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
74363 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
74364 $ok = false;
74365 }
74366 });
74367
74368 return $ok ? $fromEncoding : false;
74369 }
74370
74371 public static function mb_decode_mimeheader($s)
74372 {
74373 return iconv_mime_decode($s, 2, self::$internalEncoding);
74374 }
74375
74376 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
74377 {
74378 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
74379 }
74380
74381 public static function mb_decode_numericentity($s, $convmap, $encoding = null)
74382 {
74383 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
74384 trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
74385
74386 return null;
74387 }
74388
74389 if (!\is_array($convmap) || !$convmap) {
74390 return false;
74391 }
74392
74393 if (null !== $encoding && !\is_scalar($encoding)) {
74394 trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
74395
74396 return ''; 
74397 }
74398
74399 $s = (string) $s;
74400 if ('' === $s) {
74401 return '';
74402 }
74403
74404 $encoding = self::getEncoding($encoding);
74405
74406 if ('UTF-8' === $encoding) {
74407 $encoding = null;
74408 if (!preg_match('//u', $s)) {
74409 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
74410 }
74411 } else {
74412 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
74413 }
74414
74415 $cnt = floor(\count($convmap) / 4) * 4;
74416
74417 for ($i = 0; $i < $cnt; $i += 4) {
74418
74419 $convmap[$i] += $convmap[$i + 2];
74420 $convmap[$i + 1] += $convmap[$i + 2];
74421 }
74422
74423 $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
74424 $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
74425 for ($i = 0; $i < $cnt; $i += 4) {
74426 if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
74427 return Mbstring::mb_chr($c - $convmap[$i + 2]);
74428 }
74429 }
74430
74431 return $m[0];
74432 }, $s);
74433
74434 if (null === $encoding) {
74435 return $s;
74436 }
74437
74438 return iconv('UTF-8', $encoding.'//IGNORE', $s);
74439 }
74440
74441 public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
74442 {
74443 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
74444 trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
74445
74446 return null;
74447 }
74448
74449 if (!\is_array($convmap) || !$convmap) {
74450 return false;
74451 }
74452
74453 if (null !== $encoding && !\is_scalar($encoding)) {
74454 trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
74455
74456 return null; 
74457 }
74458
74459 if (null !== $is_hex && !\is_scalar($is_hex)) {
74460 trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING);
74461
74462 return null;
74463 }
74464
74465 $s = (string) $s;
74466 if ('' === $s) {
74467 return '';
74468 }
74469
74470 $encoding = self::getEncoding($encoding);
74471
74472 if ('UTF-8' === $encoding) {
74473 $encoding = null;
74474 if (!preg_match('//u', $s)) {
74475 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
74476 }
74477 } else {
74478 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
74479 }
74480
74481 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
74482
74483 $cnt = floor(\count($convmap) / 4) * 4;
74484 $i = 0;
74485 $len = \strlen($s);
74486 $result = '';
74487
74488 while ($i < $len) {
74489 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
74490 $uchr = substr($s, $i, $ulen);
74491 $i += $ulen;
74492 $c = self::mb_ord($uchr);
74493
74494 for ($j = 0; $j < $cnt; $j += 4) {
74495 if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
74496 $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
74497 $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
74498 continue 2;
74499 }
74500 }
74501 $result .= $uchr;
74502 }
74503
74504 if (null === $encoding) {
74505 return $result;
74506 }
74507
74508 return iconv('UTF-8', $encoding.'//IGNORE', $result);
74509 }
74510
74511 public static function mb_convert_case($s, $mode, $encoding = null)
74512 {
74513 $s = (string) $s;
74514 if ('' === $s) {
74515 return '';
74516 }
74517
74518 $encoding = self::getEncoding($encoding);
74519
74520 if ('UTF-8' === $encoding) {
74521 $encoding = null;
74522 if (!preg_match('//u', $s)) {
74523 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
74524 }
74525 } else {
74526 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
74527 }
74528
74529 if (MB_CASE_TITLE == $mode) {
74530 static $titleRegexp = null;
74531 if (null === $titleRegexp) {
74532 $titleRegexp = self::getData('titleCaseRegexp');
74533 }
74534 $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s);
74535 } else {
74536 if (MB_CASE_UPPER == $mode) {
74537 static $upper = null;
74538 if (null === $upper) {
74539 $upper = self::getData('upperCase');
74540 }
74541 $map = $upper;
74542 } else {
74543 if (self::MB_CASE_FOLD === $mode) {
74544 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
74545 }
74546
74547 static $lower = null;
74548 if (null === $lower) {
74549 $lower = self::getData('lowerCase');
74550 }
74551 $map = $lower;
74552 }
74553
74554 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
74555
74556 $i = 0;
74557 $len = \strlen($s);
74558
74559 while ($i < $len) {
74560 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
74561 $uchr = substr($s, $i, $ulen);
74562 $i += $ulen;
74563
74564 if (isset($map[$uchr])) {
74565 $uchr = $map[$uchr];
74566 $nlen = \strlen($uchr);
74567
74568 if ($nlen == $ulen) {
74569 $nlen = $i;
74570 do {
74571 $s[--$nlen] = $uchr[--$ulen];
74572 } while ($ulen);
74573 } else {
74574 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
74575 $len += $nlen - $ulen;
74576 $i += $nlen - $ulen;
74577 }
74578 }
74579 }
74580 }
74581
74582 if (null === $encoding) {
74583 return $s;
74584 }
74585
74586 return iconv('UTF-8', $encoding.'//IGNORE', $s);
74587 }
74588
74589 public static function mb_internal_encoding($encoding = null)
74590 {
74591 if (null === $encoding) {
74592 return self::$internalEncoding;
74593 }
74594
74595 $encoding = self::getEncoding($encoding);
74596
74597 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
74598 self::$internalEncoding = $encoding;
74599
74600 return true;
74601 }
74602
74603 return false;
74604 }
74605
74606 public static function mb_language($lang = null)
74607 {
74608 if (null === $lang) {
74609 return self::$language;
74610 }
74611
74612 switch ($lang = strtolower($lang)) {
74613 case 'uni':
74614 case 'neutral':
74615 self::$language = $lang;
74616
74617 return true;
74618 }
74619
74620 return false;
74621 }
74622
74623 public static function mb_list_encodings()
74624 {
74625 return array('UTF-8');
74626 }
74627
74628 public static function mb_encoding_aliases($encoding)
74629 {
74630 switch (strtoupper($encoding)) {
74631 case 'UTF8':
74632 case 'UTF-8':
74633 return array('utf8');
74634 }
74635
74636 return false;
74637 }
74638
74639 public static function mb_check_encoding($var = null, $encoding = null)
74640 {
74641 if (null === $encoding) {
74642 if (null === $var) {
74643 return false;
74644 }
74645 $encoding = self::$internalEncoding;
74646 }
74647
74648 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
74649 }
74650
74651 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
74652 {
74653 if (null === $encodingList) {
74654 $encodingList = self::$encodingList;
74655 } else {
74656 if (!\is_array($encodingList)) {
74657 $encodingList = array_map('trim', explode(',', $encodingList));
74658 }
74659 $encodingList = array_map('strtoupper', $encodingList);
74660 }
74661
74662 foreach ($encodingList as $enc) {
74663 switch ($enc) {
74664 case 'ASCII':
74665 if (!preg_match('/[\x80-\xFF]/', $str)) {
74666 return $enc;
74667 }
74668 break;
74669
74670 case 'UTF8':
74671 case 'UTF-8':
74672 if (preg_match('//u', $str)) {
74673 return 'UTF-8';
74674 }
74675 break;
74676
74677 default:
74678 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
74679 return $enc;
74680 }
74681 }
74682 }
74683
74684 return false;
74685 }
74686
74687 public static function mb_detect_order($encodingList = null)
74688 {
74689 if (null === $encodingList) {
74690 return self::$encodingList;
74691 }
74692
74693 if (!\is_array($encodingList)) {
74694 $encodingList = array_map('trim', explode(',', $encodingList));
74695 }
74696 $encodingList = array_map('strtoupper', $encodingList);
74697
74698 foreach ($encodingList as $enc) {
74699 switch ($enc) {
74700 default:
74701 if (strncmp($enc, 'ISO-8859-', 9)) {
74702 return false;
74703 }
74704
74705 case 'ASCII':
74706 case 'UTF8':
74707 case 'UTF-8':
74708 }
74709 }
74710
74711 self::$encodingList = $encodingList;
74712
74713 return true;
74714 }
74715
74716 public static function mb_strlen($s, $encoding = null)
74717 {
74718 $encoding = self::getEncoding($encoding);
74719 if ('CP850' === $encoding || 'ASCII' === $encoding) {
74720 return \strlen($s);
74721 }
74722
74723 return @iconv_strlen($s, $encoding);
74724 }
74725
74726 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
74727 {
74728 $encoding = self::getEncoding($encoding);
74729 if ('CP850' === $encoding || 'ASCII' === $encoding) {
74730 return strpos($haystack, $needle, $offset);
74731 }
74732
74733 $needle = (string) $needle;
74734 if ('' === $needle) {
74735 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
74736
74737 return false;
74738 }
74739
74740 return iconv_strpos($haystack, $needle, $offset, $encoding);
74741 }
74742
74743 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
74744 {
74745 $encoding = self::getEncoding($encoding);
74746 if ('CP850' === $encoding || 'ASCII' === $encoding) {
74747 return strrpos($haystack, $needle, $offset);
74748 }
74749
74750 if ($offset != (int) $offset) {
74751 $offset = 0;
74752 } elseif ($offset = (int) $offset) {
74753 if ($offset < 0) {
74754 if (0 > $offset += self::mb_strlen($needle)) {
74755 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
74756 }
74757 $offset = 0;
74758 } else {
74759 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
74760 }
74761 }
74762
74763 $pos = iconv_strrpos($haystack, $needle, $encoding);
74764
74765 return false !== $pos ? $offset + $pos : false;
74766 }
74767
74768 public static function mb_str_split($string, $split_length = 1, $encoding = null)
74769 {
74770 if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
74771 trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING);
74772
74773 return null;
74774 }
74775
74776 if (1 > $split_length = (int) $split_length) {
74777 trigger_error('The length of each segment must be greater than zero', E_USER_WARNING);
74778
74779 return false;
74780 }
74781
74782 if (null === $encoding) {
74783 $encoding = mb_internal_encoding();
74784 }
74785
74786 if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
74787 $rx = '/(';
74788 while (65535 < $split_length) {
74789 $rx .= '.{65535}';
74790 $split_length -= 65535;
74791 }
74792 $rx .= '.{'.$split_length.'})/us';
74793
74794 return preg_split($rx, $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
74795 }
74796
74797 $result = array();
74798 $length = mb_strlen($string, $encoding);
74799
74800 for ($i = 0; $i < $length; $i += $split_length) {
74801 $result[] = mb_substr($string, $i, $split_length, $encoding);
74802 }
74803
74804 return $result;
74805 }
74806
74807 public static function mb_strtolower($s, $encoding = null)
74808 {
74809 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
74810 }
74811
74812 public static function mb_strtoupper($s, $encoding = null)
74813 {
74814 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
74815 }
74816
74817 public static function mb_substitute_character($c = null)
74818 {
74819 if (0 === strcasecmp($c, 'none')) {
74820 return true;
74821 }
74822
74823 return null !== $c ? false : 'none';
74824 }
74825
74826 public static function mb_substr($s, $start, $length = null, $encoding = null)
74827 {
74828 $encoding = self::getEncoding($encoding);
74829 if ('CP850' === $encoding || 'ASCII' === $encoding) {
74830 return (string) substr($s, $start, null === $length ? 2147483647 : $length);
74831 }
74832
74833 if ($start < 0) {
74834 $start = iconv_strlen($s, $encoding) + $start;
74835 if ($start < 0) {
74836 $start = 0;
74837 }
74838 }
74839
74840 if (null === $length) {
74841 $length = 2147483647;
74842 } elseif ($length < 0) {
74843 $length = iconv_strlen($s, $encoding) + $length - $start;
74844 if ($length < 0) {
74845 return '';
74846 }
74847 }
74848
74849 return (string) iconv_substr($s, $start, $length, $encoding);
74850 }
74851
74852 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
74853 {
74854 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
74855 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
74856
74857 return self::mb_strpos($haystack, $needle, $offset, $encoding);
74858 }
74859
74860 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
74861 {
74862 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
74863
74864 return self::getSubpart($pos, $part, $haystack, $encoding);
74865 }
74866
74867 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
74868 {
74869 $encoding = self::getEncoding($encoding);
74870 if ('CP850' === $encoding || 'ASCII' === $encoding) {
74871 $pos = strrpos($haystack, $needle);
74872 } else {
74873 $needle = self::mb_substr($needle, 0, 1, $encoding);
74874 $pos = iconv_strrpos($haystack, $needle, $encoding);
74875 }
74876
74877 return self::getSubpart($pos, $part, $haystack, $encoding);
74878 }
74879
74880 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
74881 {
74882 $needle = self::mb_substr($needle, 0, 1, $encoding);
74883 $pos = self::mb_strripos($haystack, $needle, $encoding);
74884
74885 return self::getSubpart($pos, $part, $haystack, $encoding);
74886 }
74887
74888 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
74889 {
74890 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
74891 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
74892
74893 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
74894 }
74895
74896 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
74897 {
74898 $pos = strpos($haystack, $needle);
74899 if (false === $pos) {
74900 return false;
74901 }
74902 if ($part) {
74903 return substr($haystack, 0, $pos);
74904 }
74905
74906 return substr($haystack, $pos);
74907 }
74908
74909 public static function mb_get_info($type = 'all')
74910 {
74911 $info = array(
74912 'internal_encoding' => self::$internalEncoding,
74913 'http_output' => 'pass',
74914 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
74915 'func_overload' => 0,
74916 'func_overload_list' => 'no overload',
74917 'mail_charset' => 'UTF-8',
74918 'mail_header_encoding' => 'BASE64',
74919 'mail_body_encoding' => 'BASE64',
74920 'illegal_chars' => 0,
74921 'encoding_translation' => 'Off',
74922 'language' => self::$language,
74923 'detect_order' => self::$encodingList,
74924 'substitute_character' => 'none',
74925 'strict_detection' => 'Off',
74926 );
74927
74928 if ('all' === $type) {
74929 return $info;
74930 }
74931 if (isset($info[$type])) {
74932 return $info[$type];
74933 }
74934
74935 return false;
74936 }
74937
74938 public static function mb_http_input($type = '')
74939 {
74940 return false;
74941 }
74942
74943 public static function mb_http_output($encoding = null)
74944 {
74945 return null !== $encoding ? 'pass' === $encoding : 'pass';
74946 }
74947
74948 public static function mb_strwidth($s, $encoding = null)
74949 {
74950 $encoding = self::getEncoding($encoding);
74951
74952 if ('UTF-8' !== $encoding) {
74953 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
74954 }
74955
74956 $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);
74957
74958 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
74959 }
74960
74961 public static function mb_substr_count($haystack, $needle, $encoding = null)
74962 {
74963 return substr_count($haystack, $needle);
74964 }
74965
74966 public static function mb_output_handler($contents, $status)
74967 {
74968 return $contents;
74969 }
74970
74971 public static function mb_chr($code, $encoding = null)
74972 {
74973 if (0x80 > $code %= 0x200000) {
74974 $s = \chr($code);
74975 } elseif (0x800 > $code) {
74976 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
74977 } elseif (0x10000 > $code) {
74978 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
74979 } else {
74980 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
74981 }
74982
74983 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
74984 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
74985 }
74986
74987 return $s;
74988 }
74989
74990 public static function mb_ord($s, $encoding = null)
74991 {
74992 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
74993 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
74994 }
74995
74996 if (1 === \strlen($s)) {
74997 return \ord($s);
74998 }
74999
75000 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
75001 if (0xF0 <= $code) {
75002 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
75003 }
75004 if (0xE0 <= $code) {
75005 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
75006 }
75007 if (0xC0 <= $code) {
75008 return (($code - 0xC0) << 6) + $s[2] - 0x80;
75009 }
75010
75011 return $code;
75012 }
75013
75014 private static function getSubpart($pos, $part, $haystack, $encoding)
75015 {
75016 if (false === $pos) {
75017 return false;
75018 }
75019 if ($part) {
75020 return self::mb_substr($haystack, 0, $pos, $encoding);
75021 }
75022
75023 return self::mb_substr($haystack, $pos, null, $encoding);
75024 }
75025
75026 private static function html_encoding_callback(array $m)
75027 {
75028 $i = 1;
75029 $entities = '';
75030 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
75031
75032 while (isset($m[$i])) {
75033 if (0x80 > $m[$i]) {
75034 $entities .= \chr($m[$i++]);
75035 continue;
75036 }
75037 if (0xF0 <= $m[$i]) {
75038 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
75039 } elseif (0xE0 <= $m[$i]) {
75040 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
75041 } else {
75042 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
75043 }
75044
75045 $entities .= '&#'.$c.';';
75046 }
75047
75048 return $entities;
75049 }
75050
75051 private static function title_case(array $s)
75052 {
75053 return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8');
75054 }
75055
75056 private static function getData($file)
75057 {
75058 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
75059 return require $file;
75060 }
75061
75062 return false;
75063 }
75064
75065 private static function getEncoding($encoding)
75066 {
75067 if (null === $encoding) {
75068 return self::$internalEncoding;
75069 }
75070
75071 if ('UTF-8' === $encoding) {
75072 return 'UTF-8';
75073 }
75074
75075 $encoding = strtoupper($encoding);
75076
75077 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
75078 return 'CP850';
75079 }
75080
75081 if ('UTF8' === $encoding) {
75082 return 'UTF-8';
75083 }
75084
75085 return $encoding;
75086 }
75087 }
75088 <?php
75089
75090 return array (
75091 'A' => 'a',
75092 'B' => 'b',
75093 'C' => 'c',
75094 'D' => 'd',
75095 'E' => 'e',
75096 'F' => 'f',
75097 'G' => 'g',
75098 'H' => 'h',
75099 'I' => 'i',
75100 'J' => 'j',
75101 'K' => 'k',
75102 'L' => 'l',
75103 'M' => 'm',
75104 'N' => 'n',
75105 'O' => 'o',
75106 'P' => 'p',
75107 'Q' => 'q',
75108 'R' => 'r',
75109 'S' => 's',
75110 'T' => 't',
75111 'U' => 'u',
75112 'V' => 'v',
75113 'W' => 'w',
75114 'X' => 'x',
75115 'Y' => 'y',
75116 'Z' => 'z',
75117 'À' => 'à',
75118 'Á' => 'á',
75119 'Â' => 'â',
75120 'Ã' => 'ã',
75121 'Ä' => 'ä',
75122 'Å' => 'å',
75123 'Æ' => 'æ',
75124 'Ç' => 'ç',
75125 'È' => 'è',
75126 'É' => 'é',
75127 'Ê' => 'ê',
75128 'Ë' => 'ë',
75129 'Ì' => 'ì',
75130 'Í' => 'í',
75131 'Î' => 'î',
75132 'Ï' => 'ï',
75133 'Ð' => 'ð',
75134 'Ñ' => 'ñ',
75135 'Ò' => 'ò',
75136 'Ó' => 'ó',
75137 'Ô' => 'ô',
75138 'Õ' => 'õ',
75139 'Ö' => 'ö',
75140 'Ø' => 'ø',
75141 'Ù' => 'ù',
75142 'Ú' => 'ú',
75143 'Û' => 'û',
75144 'Ü' => 'ü',
75145 'Ý' => 'ý',
75146 'Þ' => 'þ',
75147 'Ā' => 'ā',
75148 'Ă' => 'ă',
75149 'Ą' => 'ą',
75150 'Ć' => 'ć',
75151 'Ĉ' => 'ĉ',
75152 'Ċ' => 'ċ',
75153 'Č' => 'č',
75154 'Ď' => 'ď',
75155 'Đ' => 'đ',
75156 'Ē' => 'ē',
75157 'Ĕ' => 'ĕ',
75158 'Ė' => 'ė',
75159 'Ę' => 'ę',
75160 'Ě' => 'ě',
75161 'Ĝ' => 'ĝ',
75162 'Ğ' => 'ğ',
75163 'Ġ' => 'ġ',
75164 'Ģ' => 'ģ',
75165 'Ĥ' => 'ĥ',
75166 'Ħ' => 'ħ',
75167 'Ĩ' => 'ĩ',
75168 'Ī' => 'ī',
75169 'Ĭ' => 'ĭ',
75170 'Į' => 'į',
75171 'İ' => 'i',
75172 'IJ' => 'ij',
75173 'Ĵ' => 'ĵ',
75174 'Ķ' => 'ķ',
75175 'Ĺ' => 'ĺ',
75176 'Ļ' => 'ļ',
75177 'Ľ' => 'ľ',
75178 'Ŀ' => 'ŀ',
75179 'Ł' => 'ł',
75180 'Ń' => 'ń',
75181 'Ņ' => 'ņ',
75182 'Ň' => 'ň',
75183 'Ŋ' => 'ŋ',
75184 'Ō' => 'ō',
75185 'Ŏ' => 'ŏ',
75186 'Ő' => 'ő',
75187 'Œ' => 'œ',
75188 'Ŕ' => 'ŕ',
75189 'Ŗ' => 'ŗ',
75190 'Ř' => 'ř',
75191 'Ś' => 'ś',
75192 'Ŝ' => 'ŝ',
75193 'Ş' => 'ş',
75194 'Š' => 'š',
75195 'Ţ' => 'ţ',
75196 'Ť' => 'ť',
75197 'Ŧ' => 'ŧ',
75198 'Ũ' => 'ũ',
75199 'Ū' => 'ū',
75200 'Ŭ' => 'ŭ',
75201 'Ů' => 'ů',
75202 'Ű' => 'ű',
75203 'Ų' => 'ų',
75204 'Ŵ' => 'ŵ',
75205 'Ŷ' => 'ŷ',
75206 'Ÿ' => 'ÿ',
75207 'Ź' => 'ź',
75208 'Ż' => 'ż',
75209 'Ž' => 'ž',
75210 'Ɓ' => 'ɓ',
75211 'Ƃ' => 'ƃ',
75212 'Ƅ' => 'ƅ',
75213 'Ɔ' => 'ɔ',
75214 'Ƈ' => 'ƈ',
75215 'Ɖ' => 'ɖ',
75216 'Ɗ' => 'ɗ',
75217 'Ƌ' => 'ƌ',
75218 'Ǝ' => 'ǝ',
75219 'Ə' => 'ə',
75220 'Ɛ' => 'ɛ',
75221 'Ƒ' => 'ƒ',
75222 'Ɠ' => 'ɠ',
75223 'Ɣ' => 'ɣ',
75224 'Ɩ' => 'ɩ',
75225 'Ɨ' => 'ɨ',
75226 'Ƙ' => 'ƙ',
75227 'Ɯ' => 'ɯ',
75228 'Ɲ' => 'ɲ',
75229 'Ɵ' => 'ɵ',
75230 'Ơ' => 'ơ',
75231 'Ƣ' => 'ƣ',
75232 'Ƥ' => 'ƥ',
75233 'Ʀ' => 'ʀ',
75234 'Ƨ' => 'ƨ',
75235 'Ʃ' => 'ʃ',
75236 'Ƭ' => 'ƭ',
75237 'Ʈ' => 'ʈ',
75238 'Ư' => 'ư',
75239 'Ʊ' => 'ʊ',
75240 'Ʋ' => 'ʋ',
75241 'Ƴ' => 'ƴ',
75242 'Ƶ' => 'ƶ',
75243 'Ʒ' => 'ʒ',
75244 'Ƹ' => 'ƹ',
75245 'Ƽ' => 'ƽ',
75246 'DŽ' => 'dž',
75247 'Dž' => 'dž',
75248 'LJ' => 'lj',
75249 'Lj' => 'lj',
75250 'NJ' => 'nj',
75251 'Nj' => 'nj',
75252 'Ǎ' => 'ǎ',
75253 'Ǐ' => 'ǐ',
75254 'Ǒ' => 'ǒ',
75255 'Ǔ' => 'ǔ',
75256 'Ǖ' => 'ǖ',
75257 'Ǘ' => 'ǘ',
75258 'Ǚ' => 'ǚ',
75259 'Ǜ' => 'ǜ',
75260 'Ǟ' => 'ǟ',
75261 'Ǡ' => 'ǡ',
75262 'Ǣ' => 'ǣ',
75263 'Ǥ' => 'ǥ',
75264 'Ǧ' => 'ǧ',
75265 'Ǩ' => 'ǩ',
75266 'Ǫ' => 'ǫ',
75267 'Ǭ' => 'ǭ',
75268 'Ǯ' => 'ǯ',
75269 'DZ' => 'dz',
75270 'Dz' => 'dz',
75271 'Ǵ' => 'ǵ',
75272 'Ƕ' => 'ƕ',
75273 'Ƿ' => 'ƿ',
75274 'Ǹ' => 'ǹ',
75275 'Ǻ' => 'ǻ',
75276 'Ǽ' => 'ǽ',
75277 'Ǿ' => 'ǿ',
75278 'Ȁ' => 'ȁ',
75279 'Ȃ' => 'ȃ',
75280 'Ȅ' => 'ȅ',
75281 'Ȇ' => 'ȇ',
75282 'Ȉ' => 'ȉ',
75283 'Ȋ' => 'ȋ',
75284 'Ȍ' => 'ȍ',
75285 'Ȏ' => 'ȏ',
75286 'Ȑ' => 'ȑ',
75287 'Ȓ' => 'ȓ',
75288 'Ȕ' => 'ȕ',
75289 'Ȗ' => 'ȗ',
75290 'Ș' => 'ș',
75291 'Ț' => 'ț',
75292 'Ȝ' => 'ȝ',
75293 'Ȟ' => 'ȟ',
75294 'Ƞ' => 'ƞ',
75295 'Ȣ' => 'ȣ',
75296 'Ȥ' => 'ȥ',
75297 'Ȧ' => 'ȧ',
75298 'Ȩ' => 'ȩ',
75299 'Ȫ' => 'ȫ',
75300 'Ȭ' => 'ȭ',
75301 'Ȯ' => 'ȯ',
75302 'Ȱ' => 'ȱ',
75303 'Ȳ' => 'ȳ',
75304 'Ⱥ' => 'ⱥ',
75305 'Ȼ' => 'ȼ',
75306 'Ƚ' => 'ƚ',
75307 'Ⱦ' => 'ⱦ',
75308 'Ɂ' => 'ɂ',
75309 'Ƀ' => 'ƀ',
75310 'Ʉ' => 'ʉ',
75311 'Ʌ' => 'ʌ',
75312 'Ɇ' => 'ɇ',
75313 'Ɉ' => 'ɉ',
75314 'Ɋ' => 'ɋ',
75315 'Ɍ' => 'ɍ',
75316 'Ɏ' => 'ɏ',
75317 'Ͱ' => 'ͱ',
75318 'Ͳ' => 'ͳ',
75319 'Ͷ' => 'ͷ',
75320 'Ϳ' => 'ϳ',
75321 'Ά' => 'ά',
75322 'Έ' => 'έ',
75323 'Ή' => 'ή',
75324 'Ί' => 'ί',
75325 'Ό' => 'ό',
75326 'Ύ' => 'ύ',
75327 'Ώ' => 'ώ',
75328 'Α' => 'α',
75329 'Β' => 'β',
75330 'Γ' => 'γ',
75331 'Δ' => 'δ',
75332 'Ε' => 'ε',
75333 'Ζ' => 'ζ',
75334 'Η' => 'η',
75335 'Θ' => 'θ',
75336 'Ι' => 'ι',
75337 'Κ' => 'κ',
75338 'Λ' => 'λ',
75339 'Μ' => 'μ',
75340 'Ν' => 'ν',
75341 'Ξ' => 'ξ',
75342 'Ο' => 'ο',
75343 'Π' => 'π',
75344 'Ρ' => 'ρ',
75345 'Σ' => 'σ',
75346 'Τ' => 'τ',
75347 'Υ' => 'υ',
75348 'Φ' => 'φ',
75349 'Χ' => 'χ',
75350 'Ψ' => 'ψ',
75351 'Ω' => 'ω',
75352 'Ϊ' => 'ϊ',
75353 'Ϋ' => 'ϋ',
75354 'Ϗ' => 'ϗ',
75355 'Ϙ' => 'ϙ',
75356 'Ϛ' => 'ϛ',
75357 'Ϝ' => 'ϝ',
75358 'Ϟ' => 'ϟ',
75359 'Ϡ' => 'ϡ',
75360 'Ϣ' => 'ϣ',
75361 'Ϥ' => 'ϥ',
75362 'Ϧ' => 'ϧ',
75363 'Ϩ' => 'ϩ',
75364 'Ϫ' => 'ϫ',
75365 'Ϭ' => 'ϭ',
75366 'Ϯ' => 'ϯ',
75367 'ϴ' => 'θ',
75368 'Ϸ' => 'ϸ',
75369 'Ϲ' => 'ϲ',
75370 'Ϻ' => 'ϻ',
75371 'Ͻ' => 'ͻ',
75372 'Ͼ' => 'ͼ',
75373 'Ͽ' => 'ͽ',
75374 'Ѐ' => 'ѐ',
75375 'Ё' => 'ё',
75376 'Ђ' => 'ђ',
75377 'Ѓ' => 'ѓ',
75378 'Є' => 'є',
75379 'Ѕ' => 'ѕ',
75380 'І' => 'і',
75381 'Ї' => 'ї',
75382 'Ј' => 'ј',
75383 'Љ' => 'љ',
75384 'Њ' => 'њ',
75385 'Ћ' => 'ћ',
75386 'Ќ' => 'ќ',
75387 'Ѝ' => 'ѝ',
75388 'Ў' => 'ў',
75389 'Џ' => 'џ',
75390 'А' => 'а',
75391 'Б' => 'б',
75392 'В' => 'в',
75393 'Г' => 'г',
75394 'Д' => 'д',
75395 'Е' => 'е',
75396 'Ж' => 'ж',
75397 'З' => 'з',
75398 'И' => 'и',
75399 'Й' => 'й',
75400 'К' => 'к',
75401 'Л' => 'л',
75402 'М' => 'м',
75403 'Н' => 'н',
75404 'О' => 'о',
75405 'П' => 'п',
75406 'Р' => 'р',
75407 'С' => 'с',
75408 'Т' => 'т',
75409 'У' => 'у',
75410 'Ф' => 'ф',
75411 'Х' => 'х',
75412 'Ц' => 'ц',
75413 'Ч' => 'ч',
75414 'Ш' => 'ш',
75415 'Щ' => 'щ',
75416 'Ъ' => 'ъ',
75417 'Ы' => 'ы',
75418 'Ь' => 'ь',
75419 'Э' => 'э',
75420 'Ю' => 'ю',
75421 'Я' => 'я',
75422 'Ѡ' => 'ѡ',
75423 'Ѣ' => 'ѣ',
75424 'Ѥ' => 'ѥ',
75425 'Ѧ' => 'ѧ',
75426 'Ѩ' => 'ѩ',
75427 'Ѫ' => 'ѫ',
75428 'Ѭ' => 'ѭ',
75429 'Ѯ' => 'ѯ',
75430 'Ѱ' => 'ѱ',
75431 'Ѳ' => 'ѳ',
75432 'Ѵ' => 'ѵ',
75433 'Ѷ' => 'ѷ',
75434 'Ѹ' => 'ѹ',
75435 'Ѻ' => 'ѻ',
75436 'Ѽ' => 'ѽ',
75437 'Ѿ' => 'ѿ',
75438 'Ҁ' => 'ҁ',
75439 'Ҋ' => 'ҋ',
75440 'Ҍ' => 'ҍ',
75441 'Ҏ' => 'ҏ',
75442 'Ґ' => 'ґ',
75443 'Ғ' => 'ғ',
75444 'Ҕ' => 'ҕ',
75445 'Җ' => 'җ',
75446 'Ҙ' => 'ҙ',
75447 'Қ' => 'қ',
75448 'Ҝ' => 'ҝ',
75449 'Ҟ' => 'ҟ',
75450 'Ҡ' => 'ҡ',
75451 'Ң' => 'ң',
75452 'Ҥ' => 'ҥ',
75453 'Ҧ' => 'ҧ',
75454 'Ҩ' => 'ҩ',
75455 'Ҫ' => 'ҫ',
75456 'Ҭ' => 'ҭ',
75457 'Ү' => 'ү',
75458 'Ұ' => 'ұ',
75459 'Ҳ' => 'ҳ',
75460 'Ҵ' => 'ҵ',
75461 'Ҷ' => 'ҷ',
75462 'Ҹ' => 'ҹ',
75463 'Һ' => 'һ',
75464 'Ҽ' => 'ҽ',
75465 'Ҿ' => 'ҿ',
75466 'Ӏ' => 'ӏ',
75467 'Ӂ' => 'ӂ',
75468 'Ӄ' => 'ӄ',
75469 'Ӆ' => 'ӆ',
75470 'Ӈ' => 'ӈ',
75471 'Ӊ' => 'ӊ',
75472 'Ӌ' => 'ӌ',
75473 'Ӎ' => 'ӎ',
75474 'Ӑ' => 'ӑ',
75475 'Ӓ' => 'ӓ',
75476 'Ӕ' => 'ӕ',
75477 'Ӗ' => 'ӗ',
75478 'Ә' => 'ә',
75479 'Ӛ' => 'ӛ',
75480 'Ӝ' => 'ӝ',
75481 'Ӟ' => 'ӟ',
75482 'Ӡ' => 'ӡ',
75483 'Ӣ' => 'ӣ',
75484 'Ӥ' => 'ӥ',
75485 'Ӧ' => 'ӧ',
75486 'Ө' => 'ө',
75487 'Ӫ' => 'ӫ',
75488 'Ӭ' => 'ӭ',
75489 'Ӯ' => 'ӯ',
75490 'Ӱ' => 'ӱ',
75491 'Ӳ' => 'ӳ',
75492 'Ӵ' => 'ӵ',
75493 'Ӷ' => 'ӷ',
75494 'Ӹ' => 'ӹ',
75495 'Ӻ' => 'ӻ',
75496 'Ӽ' => 'ӽ',
75497 'Ӿ' => 'ӿ',
75498 'Ԁ' => 'ԁ',
75499 'Ԃ' => 'ԃ',
75500 'Ԅ' => 'ԅ',
75501 'Ԇ' => 'ԇ',
75502 'Ԉ' => 'ԉ',
75503 'Ԋ' => 'ԋ',
75504 'Ԍ' => 'ԍ',
75505 'Ԏ' => 'ԏ',
75506 'Ԑ' => 'ԑ',
75507 'Ԓ' => 'ԓ',
75508 'Ԕ' => 'ԕ',
75509 'Ԗ' => 'ԗ',
75510 'Ԙ' => 'ԙ',
75511 'Ԛ' => 'ԛ',
75512 'Ԝ' => 'ԝ',
75513 'Ԟ' => 'ԟ',
75514 'Ԡ' => 'ԡ',
75515 'Ԣ' => 'ԣ',
75516 'Ԥ' => 'ԥ',
75517 'Ԧ' => 'ԧ',
75518 'Ԩ' => 'ԩ',
75519 'Ԫ' => 'ԫ',
75520 'Ԭ' => 'ԭ',
75521 'Ԯ' => 'ԯ',
75522 'Ա' => 'ա',
75523 'Բ' => 'բ',
75524 'Գ' => 'գ',
75525 'Դ' => 'դ',
75526 'Ե' => 'ե',
75527 'Զ' => 'զ',
75528 'Է' => 'է',
75529 'Ը' => 'ը',
75530 'Թ' => 'թ',
75531 'Ժ' => 'ժ',
75532 'Ի' => 'ի',
75533 'Լ' => 'լ',
75534 'Խ' => 'խ',
75535 'Ծ' => 'ծ',
75536 'Կ' => 'կ',
75537 'Հ' => 'հ',
75538 'Ձ' => 'ձ',
75539 'Ղ' => 'ղ',
75540 'Ճ' => 'ճ',
75541 'Մ' => 'մ',
75542 'Յ' => 'յ',
75543 'Ն' => 'ն',
75544 'Շ' => 'շ',
75545 'Ո' => 'ո',
75546 'Չ' => 'չ',
75547 'Պ' => 'պ',
75548 'Ջ' => 'ջ',
75549 'Ռ' => 'ռ',
75550 'Ս' => 'ս',
75551 'Վ' => 'վ',
75552 'Տ' => 'տ',
75553 'Ր' => 'ր',
75554 'Ց' => 'ց',
75555 'Ւ' => 'ւ',
75556 'Փ' => 'փ',
75557 'Ք' => 'ք',
75558 'Օ' => 'օ',
75559 'Ֆ' => 'ֆ',
75560 'Ⴀ' => 'ⴀ',
75561 'Ⴁ' => 'ⴁ',
75562 'Ⴂ' => 'ⴂ',
75563 'Ⴃ' => 'ⴃ',
75564 'Ⴄ' => 'ⴄ',
75565 'Ⴅ' => 'ⴅ',
75566 'Ⴆ' => 'ⴆ',
75567 'Ⴇ' => 'ⴇ',
75568 'Ⴈ' => 'ⴈ',
75569 'Ⴉ' => 'ⴉ',
75570 'Ⴊ' => 'ⴊ',
75571 'Ⴋ' => 'ⴋ',
75572 'Ⴌ' => 'ⴌ',
75573 'Ⴍ' => 'ⴍ',
75574 'Ⴎ' => 'ⴎ',
75575 'Ⴏ' => 'ⴏ',
75576 'Ⴐ' => 'ⴐ',
75577 'Ⴑ' => 'ⴑ',
75578 'Ⴒ' => 'ⴒ',
75579 'Ⴓ' => 'ⴓ',
75580 'Ⴔ' => 'ⴔ',
75581 'Ⴕ' => 'ⴕ',
75582 'Ⴖ' => 'ⴖ',
75583 'Ⴗ' => 'ⴗ',
75584 'Ⴘ' => 'ⴘ',
75585 'Ⴙ' => 'ⴙ',
75586 'Ⴚ' => 'ⴚ',
75587 'Ⴛ' => 'ⴛ',
75588 'Ⴜ' => 'ⴜ',
75589 'Ⴝ' => 'ⴝ',
75590 'Ⴞ' => 'ⴞ',
75591 'Ⴟ' => 'ⴟ',
75592 'Ⴠ' => 'ⴠ',
75593 'Ⴡ' => 'ⴡ',
75594 'Ⴢ' => 'ⴢ',
75595 'Ⴣ' => 'ⴣ',
75596 'Ⴤ' => 'ⴤ',
75597 'Ⴥ' => 'ⴥ',
75598 'Ⴧ' => 'ⴧ',
75599 'Ⴭ' => 'ⴭ',
75600 'Ꭰ' => 'ꭰ',
75601 'Ꭱ' => 'ꭱ',
75602 'Ꭲ' => 'ꭲ',
75603 'Ꭳ' => 'ꭳ',
75604 'Ꭴ' => 'ꭴ',
75605 'Ꭵ' => 'ꭵ',
75606 'Ꭶ' => 'ꭶ',
75607 'Ꭷ' => 'ꭷ',
75608 'Ꭸ' => 'ꭸ',
75609 'Ꭹ' => 'ꭹ',
75610 'Ꭺ' => 'ꭺ',
75611 'Ꭻ' => 'ꭻ',
75612 'Ꭼ' => 'ꭼ',
75613 'Ꭽ' => 'ꭽ',
75614 'Ꭾ' => 'ꭾ',
75615 'Ꭿ' => 'ꭿ',
75616 'Ꮀ' => 'ꮀ',
75617 'Ꮁ' => 'ꮁ',
75618 'Ꮂ' => 'ꮂ',
75619 'Ꮃ' => 'ꮃ',
75620 'Ꮄ' => 'ꮄ',
75621 'Ꮅ' => 'ꮅ',
75622 'Ꮆ' => 'ꮆ',
75623 'Ꮇ' => 'ꮇ',
75624 'Ꮈ' => 'ꮈ',
75625 'Ꮉ' => 'ꮉ',
75626 'Ꮊ' => 'ꮊ',
75627 'Ꮋ' => 'ꮋ',
75628 'Ꮌ' => 'ꮌ',
75629 'Ꮍ' => 'ꮍ',
75630 'Ꮎ' => 'ꮎ',
75631 'Ꮏ' => 'ꮏ',
75632 'Ꮐ' => 'ꮐ',
75633 'Ꮑ' => 'ꮑ',
75634 'Ꮒ' => 'ꮒ',
75635 'Ꮓ' => 'ꮓ',
75636 'Ꮔ' => 'ꮔ',
75637 'Ꮕ' => 'ꮕ',
75638 'Ꮖ' => 'ꮖ',
75639 'Ꮗ' => 'ꮗ',
75640 'Ꮘ' => 'ꮘ',
75641 'Ꮙ' => 'ꮙ',
75642 'Ꮚ' => 'ꮚ',
75643 'Ꮛ' => 'ꮛ',
75644 'Ꮜ' => 'ꮜ',
75645 'Ꮝ' => 'ꮝ',
75646 'Ꮞ' => 'ꮞ',
75647 'Ꮟ' => 'ꮟ',
75648 'Ꮠ' => 'ꮠ',
75649 'Ꮡ' => 'ꮡ',
75650 'Ꮢ' => 'ꮢ',
75651 'Ꮣ' => 'ꮣ',
75652 'Ꮤ' => 'ꮤ',
75653 'Ꮥ' => 'ꮥ',
75654 'Ꮦ' => 'ꮦ',
75655 'Ꮧ' => 'ꮧ',
75656 'Ꮨ' => 'ꮨ',
75657 'Ꮩ' => 'ꮩ',
75658 'Ꮪ' => 'ꮪ',
75659 'Ꮫ' => 'ꮫ',
75660 'Ꮬ' => 'ꮬ',
75661 'Ꮭ' => 'ꮭ',
75662 'Ꮮ' => 'ꮮ',
75663 'Ꮯ' => 'ꮯ',
75664 'Ꮰ' => 'ꮰ',
75665 'Ꮱ' => 'ꮱ',
75666 'Ꮲ' => 'ꮲ',
75667 'Ꮳ' => 'ꮳ',
75668 'Ꮴ' => 'ꮴ',
75669 'Ꮵ' => 'ꮵ',
75670 'Ꮶ' => 'ꮶ',
75671 'Ꮷ' => 'ꮷ',
75672 'Ꮸ' => 'ꮸ',
75673 'Ꮹ' => 'ꮹ',
75674 'Ꮺ' => 'ꮺ',
75675 'Ꮻ' => 'ꮻ',
75676 'Ꮼ' => 'ꮼ',
75677 'Ꮽ' => 'ꮽ',
75678 'Ꮾ' => 'ꮾ',
75679 'Ꮿ' => 'ꮿ',
75680 'Ᏸ' => 'ᏸ',
75681 'Ᏹ' => 'ᏹ',
75682 'Ᏺ' => 'ᏺ',
75683 'Ᏻ' => 'ᏻ',
75684 'Ᏼ' => 'ᏼ',
75685 'Ᏽ' => 'ᏽ',
75686 'Ა' => 'ა',
75687 'Ბ' => 'ბ',
75688 'Გ' => 'გ',
75689 'Დ' => 'დ',
75690 'Ე' => 'ე',
75691 'Ვ' => 'ვ',
75692 'Ზ' => 'ზ',
75693 'Თ' => 'თ',
75694 'Ი' => 'ი',
75695 'Კ' => 'კ',
75696 'Ლ' => 'ლ',
75697 'Მ' => 'მ',
75698 'Ნ' => 'ნ',
75699 'Ო' => 'ო',
75700 'Პ' => 'პ',
75701 'Ჟ' => 'ჟ',
75702 'Რ' => 'რ',
75703 'Ს' => 'ს',
75704 'Ტ' => 'ტ',
75705 'Უ' => 'უ',
75706 'Ფ' => 'ფ',
75707 'Ქ' => 'ქ',
75708 'Ღ' => 'ღ',
75709 'Ყ' => 'ყ',
75710 'Შ' => 'შ',
75711 'Ჩ' => 'ჩ',
75712 'Ც' => 'ც',
75713 'Ძ' => 'ძ',
75714 'Წ' => 'წ',
75715 'Ჭ' => 'ჭ',
75716 'Ხ' => 'ხ',
75717 'Ჯ' => 'ჯ',
75718 'Ჰ' => 'ჰ',
75719 'Ჱ' => 'ჱ',
75720 'Ჲ' => 'ჲ',
75721 'Ჳ' => 'ჳ',
75722 'Ჴ' => 'ჴ',
75723 'Ჵ' => 'ჵ',
75724 'Ჶ' => 'ჶ',
75725 'Ჷ' => 'ჷ',
75726 'Ჸ' => 'ჸ',
75727 'Ჹ' => 'ჹ',
75728 'Ჺ' => 'ჺ',
75729 'Ჽ' => 'ჽ',
75730 'Ჾ' => 'ჾ',
75731 'Ჿ' => 'ჿ',
75732 'Ḁ' => 'ḁ',
75733 'Ḃ' => 'ḃ',
75734 'Ḅ' => 'ḅ',
75735 'Ḇ' => 'ḇ',
75736 'Ḉ' => 'ḉ',
75737 'Ḋ' => 'ḋ',
75738 'Ḍ' => 'ḍ',
75739 'Ḏ' => 'ḏ',
75740 'Ḑ' => 'ḑ',
75741 'Ḓ' => 'ḓ',
75742 'Ḕ' => 'ḕ',
75743 'Ḗ' => 'ḗ',
75744 'Ḙ' => 'ḙ',
75745 'Ḛ' => 'ḛ',
75746 'Ḝ' => 'ḝ',
75747 'Ḟ' => 'ḟ',
75748 'Ḡ' => 'ḡ',
75749 'Ḣ' => 'ḣ',
75750 'Ḥ' => 'ḥ',
75751 'Ḧ' => 'ḧ',
75752 'Ḩ' => 'ḩ',
75753 'Ḫ' => 'ḫ',
75754 'Ḭ' => 'ḭ',
75755 'Ḯ' => 'ḯ',
75756 'Ḱ' => 'ḱ',
75757 'Ḳ' => 'ḳ',
75758 'Ḵ' => 'ḵ',
75759 'Ḷ' => 'ḷ',
75760 'Ḹ' => 'ḹ',
75761 'Ḻ' => 'ḻ',
75762 'Ḽ' => 'ḽ',
75763 'Ḿ' => 'ḿ',
75764 'Ṁ' => 'ṁ',
75765 'Ṃ' => 'ṃ',
75766 'Ṅ' => 'ṅ',
75767 'Ṇ' => 'ṇ',
75768 'Ṉ' => 'ṉ',
75769 'Ṋ' => 'ṋ',
75770 'Ṍ' => 'ṍ',
75771 'Ṏ' => 'ṏ',
75772 'Ṑ' => 'ṑ',
75773 'Ṓ' => 'ṓ',
75774 'Ṕ' => 'ṕ',
75775 'Ṗ' => 'ṗ',
75776 'Ṙ' => 'ṙ',
75777 'Ṛ' => 'ṛ',
75778 'Ṝ' => 'ṝ',
75779 'Ṟ' => 'ṟ',
75780 'Ṡ' => 'ṡ',
75781 'Ṣ' => 'ṣ',
75782 'Ṥ' => 'ṥ',
75783 'Ṧ' => 'ṧ',
75784 'Ṩ' => 'ṩ',
75785 'Ṫ' => 'ṫ',
75786 'Ṭ' => 'ṭ',
75787 'Ṯ' => 'ṯ',
75788 'Ṱ' => 'ṱ',
75789 'Ṳ' => 'ṳ',
75790 'Ṵ' => 'ṵ',
75791 'Ṷ' => 'ṷ',
75792 'Ṹ' => 'ṹ',
75793 'Ṻ' => 'ṻ',
75794 'Ṽ' => 'ṽ',
75795 'Ṿ' => 'ṿ',
75796 'Ẁ' => 'ẁ',
75797 'Ẃ' => 'ẃ',
75798 'Ẅ' => 'ẅ',
75799 'Ẇ' => 'ẇ',
75800 'Ẉ' => 'ẉ',
75801 'Ẋ' => 'ẋ',
75802 'Ẍ' => 'ẍ',
75803 'Ẏ' => 'ẏ',
75804 'Ẑ' => 'ẑ',
75805 'Ẓ' => 'ẓ',
75806 'Ẕ' => 'ẕ',
75807 'ẞ' => 'ß',
75808 'Ạ' => 'ạ',
75809 'Ả' => 'ả',
75810 'Ấ' => 'ấ',
75811 'Ầ' => 'ầ',
75812 'Ẩ' => 'ẩ',
75813 'Ẫ' => 'ẫ',
75814 'Ậ' => 'ậ',
75815 'Ắ' => 'ắ',
75816 'Ằ' => 'ằ',
75817 'Ẳ' => 'ẳ',
75818 'Ẵ' => 'ẵ',
75819 'Ặ' => 'ặ',
75820 'Ẹ' => 'ẹ',
75821 'Ẻ' => 'ẻ',
75822 'Ẽ' => 'ẽ',
75823 'Ế' => 'ế',
75824 'Ề' => 'ề',
75825 'Ể' => 'ể',
75826 'Ễ' => 'ễ',
75827 'Ệ' => 'ệ',
75828 'Ỉ' => 'ỉ',
75829 'Ị' => 'ị',
75830 'Ọ' => 'ọ',
75831 'Ỏ' => 'ỏ',
75832 'Ố' => 'ố',
75833 'Ồ' => 'ồ',
75834 'Ổ' => 'ổ',
75835 'Ỗ' => 'ỗ',
75836 'Ộ' => 'ộ',
75837 'Ớ' => 'ớ',
75838 'Ờ' => 'ờ',
75839 'Ở' => 'ở',
75840 'Ỡ' => 'ỡ',
75841 'Ợ' => 'ợ',
75842 'Ụ' => 'ụ',
75843 'Ủ' => 'ủ',
75844 'Ứ' => 'ứ',
75845 'Ừ' => 'ừ',
75846 'Ử' => 'ử',
75847 'Ữ' => 'ữ',
75848 'Ự' => 'ự',
75849 'Ỳ' => 'ỳ',
75850 'Ỵ' => 'ỵ',
75851 'Ỷ' => 'ỷ',
75852 'Ỹ' => 'ỹ',
75853 'Ỻ' => 'ỻ',
75854 'Ỽ' => 'ỽ',
75855 'Ỿ' => 'ỿ',
75856 'Ἀ' => 'ἀ',
75857 'Ἁ' => 'ἁ',
75858 'Ἂ' => 'ἂ',
75859 'Ἃ' => 'ἃ',
75860 'Ἄ' => 'ἄ',
75861 'Ἅ' => 'ἅ',
75862 'Ἆ' => 'ἆ',
75863 'Ἇ' => 'ἇ',
75864 'Ἐ' => 'ἐ',
75865 'Ἑ' => 'ἑ',
75866 'Ἒ' => 'ἒ',
75867 'Ἓ' => 'ἓ',
75868 'Ἔ' => 'ἔ',
75869 'Ἕ' => 'ἕ',
75870 'Ἠ' => 'ἠ',
75871 'Ἡ' => 'ἡ',
75872 'Ἢ' => 'ἢ',
75873 'Ἣ' => 'ἣ',
75874 'Ἤ' => 'ἤ',
75875 'Ἥ' => 'ἥ',
75876 'Ἦ' => 'ἦ',
75877 'Ἧ' => 'ἧ',
75878 'Ἰ' => 'ἰ',
75879 'Ἱ' => 'ἱ',
75880 'Ἲ' => 'ἲ',
75881 'Ἳ' => 'ἳ',
75882 'Ἴ' => 'ἴ',
75883 'Ἵ' => 'ἵ',
75884 'Ἶ' => 'ἶ',
75885 'Ἷ' => 'ἷ',
75886 'Ὀ' => 'ὀ',
75887 'Ὁ' => 'ὁ',
75888 'Ὂ' => 'ὂ',
75889 'Ὃ' => 'ὃ',
75890 'Ὄ' => 'ὄ',
75891 'Ὅ' => 'ὅ',
75892 'Ὑ' => 'ὑ',
75893 'Ὓ' => 'ὓ',
75894 'Ὕ' => 'ὕ',
75895 'Ὗ' => 'ὗ',
75896 'Ὠ' => 'ὠ',
75897 'Ὡ' => 'ὡ',
75898 'Ὢ' => 'ὢ',
75899 'Ὣ' => 'ὣ',
75900 'Ὤ' => 'ὤ',
75901 'Ὥ' => 'ὥ',
75902 'Ὦ' => 'ὦ',
75903 'Ὧ' => 'ὧ',
75904 'ᾈ' => 'ᾀ',
75905 'ᾉ' => 'ᾁ',
75906 'ᾊ' => 'ᾂ',
75907 'ᾋ' => 'ᾃ',
75908 'ᾌ' => 'ᾄ',
75909 'ᾍ' => 'ᾅ',
75910 'ᾎ' => 'ᾆ',
75911 'ᾏ' => 'ᾇ',
75912 'ᾘ' => 'ᾐ',
75913 'ᾙ' => 'ᾑ',
75914 'ᾚ' => 'ᾒ',
75915 'ᾛ' => 'ᾓ',
75916 'ᾜ' => 'ᾔ',
75917 'ᾝ' => 'ᾕ',
75918 'ᾞ' => 'ᾖ',
75919 'ᾟ' => 'ᾗ',
75920 'ᾨ' => 'ᾠ',
75921 'ᾩ' => 'ᾡ',
75922 'ᾪ' => 'ᾢ',
75923 'ᾫ' => 'ᾣ',
75924 'ᾬ' => 'ᾤ',
75925 'ᾭ' => 'ᾥ',
75926 'ᾮ' => 'ᾦ',
75927 'ᾯ' => 'ᾧ',
75928 'Ᾰ' => 'ᾰ',
75929 'Ᾱ' => 'ᾱ',
75930 'Ὰ' => 'ὰ',
75931 'Ά' => 'ά',
75932 'ᾼ' => 'ᾳ',
75933 'Ὲ' => 'ὲ',
75934 'Έ' => 'έ',
75935 'Ὴ' => 'ὴ',
75936 'Ή' => 'ή',
75937 'ῌ' => 'ῃ',
75938 'Ῐ' => 'ῐ',
75939 'Ῑ' => 'ῑ',
75940 'Ὶ' => 'ὶ',
75941 'Ί' => 'ί',
75942 'Ῠ' => 'ῠ',
75943 'Ῡ' => 'ῡ',
75944 'Ὺ' => 'ὺ',
75945 'Ύ' => 'ύ',
75946 'Ῥ' => 'ῥ',
75947 'Ὸ' => 'ὸ',
75948 'Ό' => 'ό',
75949 'Ὼ' => 'ὼ',
75950 'Ώ' => 'ώ',
75951 'ῼ' => 'ῳ',
75952 'Ω' => 'ω',
75953 'K' => 'k',
75954 'Å' => 'å',
75955 'Ⅎ' => 'ⅎ',
75956 'Ⅰ' => 'ⅰ',
75957 'Ⅱ' => 'ⅱ',
75958 'Ⅲ' => 'ⅲ',
75959 'Ⅳ' => 'ⅳ',
75960 'Ⅴ' => 'ⅴ',
75961 'Ⅵ' => 'ⅵ',
75962 'Ⅶ' => 'ⅶ',
75963 'Ⅷ' => 'ⅷ',
75964 'Ⅸ' => 'ⅸ',
75965 'Ⅹ' => 'ⅹ',
75966 'Ⅺ' => 'ⅺ',
75967 'Ⅻ' => 'ⅻ',
75968 'Ⅼ' => 'ⅼ',
75969 'Ⅽ' => 'ⅽ',
75970 'Ⅾ' => 'ⅾ',
75971 'Ⅿ' => 'ⅿ',
75972 'Ↄ' => 'ↄ',
75973 'Ⓐ' => 'ⓐ',
75974 'Ⓑ' => 'ⓑ',
75975 'Ⓒ' => 'ⓒ',
75976 'Ⓓ' => 'ⓓ',
75977 'Ⓔ' => 'ⓔ',
75978 'Ⓕ' => 'ⓕ',
75979 'Ⓖ' => 'ⓖ',
75980 'Ⓗ' => 'ⓗ',
75981 'Ⓘ' => 'ⓘ',
75982 'Ⓙ' => 'ⓙ',
75983 'Ⓚ' => 'ⓚ',
75984 'Ⓛ' => 'ⓛ',
75985 'Ⓜ' => 'ⓜ',
75986 'Ⓝ' => 'ⓝ',
75987 'Ⓞ' => 'ⓞ',
75988 'Ⓟ' => 'ⓟ',
75989 'Ⓠ' => 'ⓠ',
75990 'Ⓡ' => 'ⓡ',
75991 'Ⓢ' => 'ⓢ',
75992 'Ⓣ' => 'ⓣ',
75993 'Ⓤ' => 'ⓤ',
75994 'Ⓥ' => 'ⓥ',
75995 'Ⓦ' => 'ⓦ',
75996 'Ⓧ' => 'ⓧ',
75997 'Ⓨ' => 'ⓨ',
75998 'Ⓩ' => 'ⓩ',
75999 'Ⰰ' => 'ⰰ',
76000 'Ⰱ' => 'ⰱ',
76001 'Ⰲ' => 'ⰲ',
76002 'Ⰳ' => 'ⰳ',
76003 'Ⰴ' => 'ⰴ',
76004 'Ⰵ' => 'ⰵ',
76005 'Ⰶ' => 'ⰶ',
76006 'Ⰷ' => 'ⰷ',
76007 'Ⰸ' => 'ⰸ',
76008 'Ⰹ' => 'ⰹ',
76009 'Ⰺ' => 'ⰺ',
76010 'Ⰻ' => 'ⰻ',
76011 'Ⰼ' => 'ⰼ',
76012 'Ⰽ' => 'ⰽ',
76013 'Ⰾ' => 'ⰾ',
76014 'Ⰿ' => 'ⰿ',
76015 'Ⱀ' => 'ⱀ',
76016 'Ⱁ' => 'ⱁ',
76017 'Ⱂ' => 'ⱂ',
76018 'Ⱃ' => 'ⱃ',
76019 'Ⱄ' => 'ⱄ',
76020 'Ⱅ' => 'ⱅ',
76021 'Ⱆ' => 'ⱆ',
76022 'Ⱇ' => 'ⱇ',
76023 'Ⱈ' => 'ⱈ',
76024 'Ⱉ' => 'ⱉ',
76025 'Ⱊ' => 'ⱊ',
76026 'Ⱋ' => 'ⱋ',
76027 'Ⱌ' => 'ⱌ',
76028 'Ⱍ' => 'ⱍ',
76029 'Ⱎ' => 'ⱎ',
76030 'Ⱏ' => 'ⱏ',
76031 'Ⱐ' => 'ⱐ',
76032 'Ⱑ' => 'ⱑ',
76033 'Ⱒ' => 'ⱒ',
76034 'Ⱓ' => 'ⱓ',
76035 'Ⱔ' => 'ⱔ',
76036 'Ⱕ' => 'ⱕ',
76037 'Ⱖ' => 'ⱖ',
76038 'Ⱗ' => 'ⱗ',
76039 'Ⱘ' => 'ⱘ',
76040 'Ⱙ' => 'ⱙ',
76041 'Ⱚ' => 'ⱚ',
76042 'Ⱛ' => 'ⱛ',
76043 'Ⱜ' => 'ⱜ',
76044 'Ⱝ' => 'ⱝ',
76045 'Ⱞ' => 'ⱞ',
76046 'Ⱡ' => 'ⱡ',
76047 'Ɫ' => 'ɫ',
76048 'Ᵽ' => 'ᵽ',
76049 'Ɽ' => 'ɽ',
76050 'Ⱨ' => 'ⱨ',
76051 'Ⱪ' => 'ⱪ',
76052 'Ⱬ' => 'ⱬ',
76053 'Ɑ' => 'ɑ',
76054 'Ɱ' => 'ɱ',
76055 'Ɐ' => 'ɐ',
76056 'Ɒ' => 'ɒ',
76057 'Ⱳ' => 'ⱳ',
76058 'Ⱶ' => 'ⱶ',
76059 'Ȿ' => 'ȿ',
76060 'Ɀ' => 'ɀ',
76061 'Ⲁ' => 'ⲁ',
76062 'Ⲃ' => 'ⲃ',
76063 'Ⲅ' => 'ⲅ',
76064 'Ⲇ' => 'ⲇ',
76065 'Ⲉ' => 'ⲉ',
76066 'Ⲋ' => 'ⲋ',
76067 'Ⲍ' => 'ⲍ',
76068 'Ⲏ' => 'ⲏ',
76069 'Ⲑ' => 'ⲑ',
76070 'Ⲓ' => 'ⲓ',
76071 'Ⲕ' => 'ⲕ',
76072 'Ⲗ' => 'ⲗ',
76073 'Ⲙ' => 'ⲙ',
76074 'Ⲛ' => 'ⲛ',
76075 'Ⲝ' => 'ⲝ',
76076 'Ⲟ' => 'ⲟ',
76077 'Ⲡ' => 'ⲡ',
76078 'Ⲣ' => 'ⲣ',
76079 'Ⲥ' => 'ⲥ',
76080 'Ⲧ' => 'ⲧ',
76081 'Ⲩ' => 'ⲩ',
76082 'Ⲫ' => 'ⲫ',
76083 'Ⲭ' => 'ⲭ',
76084 'Ⲯ' => 'ⲯ',
76085 'Ⲱ' => 'ⲱ',
76086 'Ⲳ' => 'ⲳ',
76087 'Ⲵ' => 'ⲵ',
76088 'Ⲷ' => 'ⲷ',
76089 'Ⲹ' => 'ⲹ',
76090 'Ⲻ' => 'ⲻ',
76091 'Ⲽ' => 'ⲽ',
76092 'Ⲿ' => 'ⲿ',
76093 'Ⳁ' => 'ⳁ',
76094 'Ⳃ' => 'ⳃ',
76095 'Ⳅ' => 'ⳅ',
76096 'Ⳇ' => 'ⳇ',
76097 'Ⳉ' => 'ⳉ',
76098 'Ⳋ' => 'ⳋ',
76099 'Ⳍ' => 'ⳍ',
76100 'Ⳏ' => 'ⳏ',
76101 'Ⳑ' => 'ⳑ',
76102 'Ⳓ' => 'ⳓ',
76103 'Ⳕ' => 'ⳕ',
76104 'Ⳗ' => 'ⳗ',
76105 'Ⳙ' => 'ⳙ',
76106 'Ⳛ' => 'ⳛ',
76107 'Ⳝ' => 'ⳝ',
76108 'Ⳟ' => 'ⳟ',
76109 'Ⳡ' => 'ⳡ',
76110 'Ⳣ' => 'ⳣ',
76111 'Ⳬ' => 'ⳬ',
76112 'Ⳮ' => 'ⳮ',
76113 'Ⳳ' => 'ⳳ',
76114 'Ꙁ' => 'ꙁ',
76115 'Ꙃ' => 'ꙃ',
76116 'Ꙅ' => 'ꙅ',
76117 'Ꙇ' => 'ꙇ',
76118 'Ꙉ' => 'ꙉ',
76119 'Ꙋ' => 'ꙋ',
76120 'Ꙍ' => 'ꙍ',
76121 'Ꙏ' => 'ꙏ',
76122 'Ꙑ' => 'ꙑ',
76123 'Ꙓ' => 'ꙓ',
76124 'Ꙕ' => 'ꙕ',
76125 'Ꙗ' => 'ꙗ',
76126 'Ꙙ' => 'ꙙ',
76127 'Ꙛ' => 'ꙛ',
76128 'Ꙝ' => 'ꙝ',
76129 'Ꙟ' => 'ꙟ',
76130 'Ꙡ' => 'ꙡ',
76131 'Ꙣ' => 'ꙣ',
76132 'Ꙥ' => 'ꙥ',
76133 'Ꙧ' => 'ꙧ',
76134 'Ꙩ' => 'ꙩ',
76135 'Ꙫ' => 'ꙫ',
76136 'Ꙭ' => 'ꙭ',
76137 'Ꚁ' => 'ꚁ',
76138 'Ꚃ' => 'ꚃ',
76139 'Ꚅ' => 'ꚅ',
76140 'Ꚇ' => 'ꚇ',
76141 'Ꚉ' => 'ꚉ',
76142 'Ꚋ' => 'ꚋ',
76143 'Ꚍ' => 'ꚍ',
76144 'Ꚏ' => 'ꚏ',
76145 'Ꚑ' => 'ꚑ',
76146 'Ꚓ' => 'ꚓ',
76147 'Ꚕ' => 'ꚕ',
76148 'Ꚗ' => 'ꚗ',
76149 'Ꚙ' => 'ꚙ',
76150 'Ꚛ' => 'ꚛ',
76151 'Ꜣ' => 'ꜣ',
76152 'Ꜥ' => 'ꜥ',
76153 'Ꜧ' => 'ꜧ',
76154 'Ꜩ' => 'ꜩ',
76155 'Ꜫ' => 'ꜫ',
76156 'Ꜭ' => 'ꜭ',
76157 'Ꜯ' => 'ꜯ',
76158 'Ꜳ' => 'ꜳ',
76159 'Ꜵ' => 'ꜵ',
76160 'Ꜷ' => 'ꜷ',
76161 'Ꜹ' => 'ꜹ',
76162 'Ꜻ' => 'ꜻ',
76163 'Ꜽ' => 'ꜽ',
76164 'Ꜿ' => 'ꜿ',
76165 'Ꝁ' => 'ꝁ',
76166 'Ꝃ' => 'ꝃ',
76167 'Ꝅ' => 'ꝅ',
76168 'Ꝇ' => 'ꝇ',
76169 'Ꝉ' => 'ꝉ',
76170 'Ꝋ' => 'ꝋ',
76171 'Ꝍ' => 'ꝍ',
76172 'Ꝏ' => 'ꝏ',
76173 'Ꝑ' => 'ꝑ',
76174 'Ꝓ' => 'ꝓ',
76175 'Ꝕ' => 'ꝕ',
76176 'Ꝗ' => 'ꝗ',
76177 'Ꝙ' => 'ꝙ',
76178 'Ꝛ' => 'ꝛ',
76179 'Ꝝ' => 'ꝝ',
76180 'Ꝟ' => 'ꝟ',
76181 'Ꝡ' => 'ꝡ',
76182 'Ꝣ' => 'ꝣ',
76183 'Ꝥ' => 'ꝥ',
76184 'Ꝧ' => 'ꝧ',
76185 'Ꝩ' => 'ꝩ',
76186 'Ꝫ' => 'ꝫ',
76187 'Ꝭ' => 'ꝭ',
76188 'Ꝯ' => 'ꝯ',
76189 'Ꝺ' => 'ꝺ',
76190 'Ꝼ' => 'ꝼ',
76191 'Ᵹ' => 'ᵹ',
76192 'Ꝿ' => 'ꝿ',
76193 'Ꞁ' => 'ꞁ',
76194 'Ꞃ' => 'ꞃ',
76195 'Ꞅ' => 'ꞅ',
76196 'Ꞇ' => 'ꞇ',
76197 'Ꞌ' => 'ꞌ',
76198 'Ɥ' => 'ɥ',
76199 'Ꞑ' => 'ꞑ',
76200 'Ꞓ' => 'ꞓ',
76201 'Ꞗ' => 'ꞗ',
76202 'Ꞙ' => 'ꞙ',
76203 'Ꞛ' => 'ꞛ',
76204 'Ꞝ' => 'ꞝ',
76205 'Ꞟ' => 'ꞟ',
76206 'Ꞡ' => 'ꞡ',
76207 'Ꞣ' => 'ꞣ',
76208 'Ꞥ' => 'ꞥ',
76209 'Ꞧ' => 'ꞧ',
76210 'Ꞩ' => 'ꞩ',
76211 'Ɦ' => 'ɦ',
76212 'Ɜ' => 'ɜ',
76213 'Ɡ' => 'ɡ',
76214 'Ɬ' => 'ɬ',
76215 'Ɪ' => 'ɪ',
76216 'Ʞ' => 'ʞ',
76217 'Ʇ' => 'ʇ',
76218 'Ʝ' => 'ʝ',
76219 'Ꭓ' => 'ꭓ',
76220 'Ꞵ' => 'ꞵ',
76221 'Ꞷ' => 'ꞷ',
76222 'Ꞹ' => 'ꞹ',
76223 'Ꞻ' => 'ꞻ',
76224 'Ꞽ' => 'ꞽ',
76225 'Ꞿ' => 'ꞿ',
76226 'Ꟃ' => 'ꟃ',
76227 'Ꞔ' => 'ꞔ',
76228 'Ʂ' => 'ʂ',
76229 'Ᶎ' => 'ᶎ',
76230 'Ꟈ' => 'ꟈ',
76231 'Ꟊ' => 'ꟊ',
76232 'Ꟶ' => 'ꟶ',
76233 'A' => 'a',
76234 'B' => 'b',
76235 'C' => 'c',
76236 'D' => 'd',
76237 'E' => 'e',
76238 'F' => 'f',
76239 'G' => 'g',
76240 'H' => 'h',
76241 'I' => 'i',
76242 'J' => 'j',
76243 'K' => 'k',
76244 'L' => 'l',
76245 'M' => 'm',
76246 'N' => 'n',
76247 'O' => 'o',
76248 'P' => 'p',
76249 'Q' => 'q',
76250 'R' => 'r',
76251 'S' => 's',
76252 'T' => 't',
76253 'U' => 'u',
76254 'V' => 'v',
76255 'W' => 'w',
76256 'X' => 'x',
76257 'Y' => 'y',
76258 'Z' => 'z',
76259 '𐐀' => '𐐨',
76260 '𐐁' => '𐐩',
76261 '𐐂' => '𐐪',
76262 '𐐃' => '𐐫',
76263 '𐐄' => '𐐬',
76264 '𐐅' => '𐐭',
76265 '𐐆' => '𐐮',
76266 '𐐇' => '𐐯',
76267 '𐐈' => '𐐰',
76268 '𐐉' => '𐐱',
76269 '𐐊' => '𐐲',
76270 '𐐋' => '𐐳',
76271 '𐐌' => '𐐴',
76272 '𐐍' => '𐐵',
76273 '𐐎' => '𐐶',
76274 '𐐏' => '𐐷',
76275 '𐐐' => '𐐸',
76276 '𐐑' => '𐐹',
76277 '𐐒' => '𐐺',
76278 '𐐓' => '𐐻',
76279 '𐐔' => '𐐼',
76280 '𐐕' => '𐐽',
76281 '𐐖' => '𐐾',
76282 '𐐗' => '𐐿',
76283 '𐐘' => '𐑀',
76284 '𐐙' => '𐑁',
76285 '𐐚' => '𐑂',
76286 '𐐛' => '𐑃',
76287 '𐐜' => '𐑄',
76288 '𐐝' => '𐑅',
76289 '𐐞' => '𐑆',
76290 '𐐟' => '𐑇',
76291 '𐐠' => '𐑈',
76292 '𐐡' => '𐑉',
76293 '𐐢' => '𐑊',
76294 '𐐣' => '𐑋',
76295 '𐐤' => '𐑌',
76296 '𐐥' => '𐑍',
76297 '𐐦' => '𐑎',
76298 '𐐧' => '𐑏',
76299 '𐒰' => '𐓘',
76300 '𐒱' => '𐓙',
76301 '𐒲' => '𐓚',
76302 '𐒳' => '𐓛',
76303 '𐒴' => '𐓜',
76304 '𐒵' => '𐓝',
76305 '𐒶' => '𐓞',
76306 '𐒷' => '𐓟',
76307 '𐒸' => '𐓠',
76308 '𐒹' => '𐓡',
76309 '𐒺' => '𐓢',
76310 '𐒻' => '𐓣',
76311 '𐒼' => '𐓤',
76312 '𐒽' => '𐓥',
76313 '𐒾' => '𐓦',
76314 '𐒿' => '𐓧',
76315 '𐓀' => '𐓨',
76316 '𐓁' => '𐓩',
76317 '𐓂' => '𐓪',
76318 '𐓃' => '𐓫',
76319 '𐓄' => '𐓬',
76320 '𐓅' => '𐓭',
76321 '𐓆' => '𐓮',
76322 '𐓇' => '𐓯',
76323 '𐓈' => '𐓰',
76324 '𐓉' => '𐓱',
76325 '𐓊' => '𐓲',
76326 '𐓋' => '𐓳',
76327 '𐓌' => '𐓴',
76328 '𐓍' => '𐓵',
76329 '𐓎' => '𐓶',
76330 '𐓏' => '𐓷',
76331 '𐓐' => '𐓸',
76332 '𐓑' => '𐓹',
76333 '𐓒' => '𐓺',
76334 '𐓓' => '𐓻',
76335 '𐲀' => '𐳀',
76336 '𐲁' => '𐳁',
76337 '𐲂' => '𐳂',
76338 '𐲃' => '𐳃',
76339 '𐲄' => '𐳄',
76340 '𐲅' => '𐳅',
76341 '𐲆' => '𐳆',
76342 '𐲇' => '𐳇',
76343 '𐲈' => '𐳈',
76344 '𐲉' => '𐳉',
76345 '𐲊' => '𐳊',
76346 '𐲋' => '𐳋',
76347 '𐲌' => '𐳌',
76348 '𐲍' => '𐳍',
76349 '𐲎' => '𐳎',
76350 '𐲏' => '𐳏',
76351 '𐲐' => '𐳐',
76352 '𐲑' => '𐳑',
76353 '𐲒' => '𐳒',
76354 '𐲓' => '𐳓',
76355 '𐲔' => '𐳔',
76356 '𐲕' => '𐳕',
76357 '𐲖' => '𐳖',
76358 '𐲗' => '𐳗',
76359 '𐲘' => '𐳘',
76360 '𐲙' => '𐳙',
76361 '𐲚' => '𐳚',
76362 '𐲛' => '𐳛',
76363 '𐲜' => '𐳜',
76364 '𐲝' => '𐳝',
76365 '𐲞' => '𐳞',
76366 '𐲟' => '𐳟',
76367 '𐲠' => '𐳠',
76368 '𐲡' => '𐳡',
76369 '𐲢' => '𐳢',
76370 '𐲣' => '𐳣',
76371 '𐲤' => '𐳤',
76372 '𐲥' => '𐳥',
76373 '𐲦' => '𐳦',
76374 '𐲧' => '𐳧',
76375 '𐲨' => '𐳨',
76376 '𐲩' => '𐳩',
76377 '𐲪' => '𐳪',
76378 '𐲫' => '𐳫',
76379 '𐲬' => '𐳬',
76380 '𐲭' => '𐳭',
76381 '𐲮' => '𐳮',
76382 '𐲯' => '𐳯',
76383 '𐲰' => '𐳰',
76384 '𐲱' => '𐳱',
76385 '𐲲' => '𐳲',
76386 '𑢠' => '𑣀',
76387 '𑢡' => '𑣁',
76388 '𑢢' => '𑣂',
76389 '𑢣' => '𑣃',
76390 '𑢤' => '𑣄',
76391 '𑢥' => '𑣅',
76392 '𑢦' => '𑣆',
76393 '𑢧' => '𑣇',
76394 '𑢨' => '𑣈',
76395 '𑢩' => '𑣉',
76396 '𑢪' => '𑣊',
76397 '𑢫' => '𑣋',
76398 '𑢬' => '𑣌',
76399 '𑢭' => '𑣍',
76400 '𑢮' => '𑣎',
76401 '𑢯' => '𑣏',
76402 '𑢰' => '𑣐',
76403 '𑢱' => '𑣑',
76404 '𑢲' => '𑣒',
76405 '𑢳' => '𑣓',
76406 '𑢴' => '𑣔',
76407 '𑢵' => '𑣕',
76408 '𑢶' => '𑣖',
76409 '𑢷' => '𑣗',
76410 '𑢸' => '𑣘',
76411 '𑢹' => '𑣙',
76412 '𑢺' => '𑣚',
76413 '𑢻' => '𑣛',
76414 '𑢼' => '𑣜',
76415 '𑢽' => '𑣝',
76416 '𑢾' => '𑣞',
76417 '𑢿' => '𑣟',
76418 '𖹀' => '𖹠',
76419 '𖹁' => '𖹡',
76420 '𖹂' => '𖹢',
76421 '𖹃' => '𖹣',
76422 '𖹄' => '𖹤',
76423 '𖹅' => '𖹥',
76424 '𖹆' => '𖹦',
76425 '𖹇' => '𖹧',
76426 '𖹈' => '𖹨',
76427 '𖹉' => '𖹩',
76428 '𖹊' => '𖹪',
76429 '𖹋' => '𖹫',
76430 '𖹌' => '𖹬',
76431 '𖹍' => '𖹭',
76432 '𖹎' => '𖹮',
76433 '𖹏' => '𖹯',
76434 '𖹐' => '𖹰',
76435 '𖹑' => '𖹱',
76436 '𖹒' => '𖹲',
76437 '𖹓' => '𖹳',
76438 '𖹔' => '𖹴',
76439 '𖹕' => '𖹵',
76440 '𖹖' => '𖹶',
76441 '𖹗' => '𖹷',
76442 '𖹘' => '𖹸',
76443 '𖹙' => '𖹹',
76444 '𖹚' => '𖹺',
76445 '𖹛' => '𖹻',
76446 '𖹜' => '𖹼',
76447 '𖹝' => '𖹽',
76448 '𖹞' => '𖹾',
76449 '𖹟' => '𖹿',
76450 '𞤀' => '𞤢',
76451 '𞤁' => '𞤣',
76452 '𞤂' => '𞤤',
76453 '𞤃' => '𞤥',
76454 '𞤄' => '𞤦',
76455 '𞤅' => '𞤧',
76456 '𞤆' => '𞤨',
76457 '𞤇' => '𞤩',
76458 '𞤈' => '𞤪',
76459 '𞤉' => '𞤫',
76460 '𞤊' => '𞤬',
76461 '𞤋' => '𞤭',
76462 '𞤌' => '𞤮',
76463 '𞤍' => '𞤯',
76464 '𞤎' => '𞤰',
76465 '𞤏' => '𞤱',
76466 '𞤐' => '𞤲',
76467 '𞤑' => '𞤳',
76468 '𞤒' => '𞤴',
76469 '𞤓' => '𞤵',
76470 '𞤔' => '𞤶',
76471 '𞤕' => '𞤷',
76472 '𞤖' => '𞤸',
76473 '𞤗' => '𞤹',
76474 '𞤘' => '𞤺',
76475 '𞤙' => '𞤻',
76476 '𞤚' => '𞤼',
76477 '𞤛' => '𞤽',
76478 '𞤜' => '𞤾',
76479 '𞤝' => '𞤿',
76480 '𞤞' => '𞥀',
76481 '𞤟' => '𞥁',
76482 '𞤠' => '𞥂',
76483 '𞤡' => '𞥃',
76484 );
76485 <?php
76486
76487
76488
76489 return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u';
76490 <?php
76491
76492 return array (
76493 'a' => 'A',
76494 'b' => 'B',
76495 'c' => 'C',
76496 'd' => 'D',
76497 'e' => 'E',
76498 'f' => 'F',
76499 'g' => 'G',
76500 'h' => 'H',
76501 'i' => 'I',
76502 'j' => 'J',
76503 'k' => 'K',
76504 'l' => 'L',
76505 'm' => 'M',
76506 'n' => 'N',
76507 'o' => 'O',
76508 'p' => 'P',
76509 'q' => 'Q',
76510 'r' => 'R',
76511 's' => 'S',
76512 't' => 'T',
76513 'u' => 'U',
76514 'v' => 'V',
76515 'w' => 'W',
76516 'x' => 'X',
76517 'y' => 'Y',
76518 'z' => 'Z',
76519 'µ' => 'Μ',
76520 'à' => 'À',
76521 'á' => 'Á',
76522 'â' => 'Â',
76523 'ã' => 'Ã',
76524 'ä' => 'Ä',
76525 'å' => 'Å',
76526 'æ' => 'Æ',
76527 'ç' => 'Ç',
76528 'è' => 'È',
76529 'é' => 'É',
76530 'ê' => 'Ê',
76531 'ë' => 'Ë',
76532 'ì' => 'Ì',
76533 'í' => 'Í',
76534 'î' => 'Î',
76535 'ï' => 'Ï',
76536 'ð' => 'Ð',
76537 'ñ' => 'Ñ',
76538 'ò' => 'Ò',
76539 'ó' => 'Ó',
76540 'ô' => 'Ô',
76541 'õ' => 'Õ',
76542 'ö' => 'Ö',
76543 'ø' => 'Ø',
76544 'ù' => 'Ù',
76545 'ú' => 'Ú',
76546 'û' => 'Û',
76547 'ü' => 'Ü',
76548 'ý' => 'Ý',
76549 'þ' => 'Þ',
76550 'ÿ' => 'Ÿ',
76551 'ā' => 'Ā',
76552 'ă' => 'Ă',
76553 'ą' => 'Ą',
76554 'ć' => 'Ć',
76555 'ĉ' => 'Ĉ',
76556 'ċ' => 'Ċ',
76557 'č' => 'Č',
76558 'ď' => 'Ď',
76559 'đ' => 'Đ',
76560 'ē' => 'Ē',
76561 'ĕ' => 'Ĕ',
76562 'ė' => 'Ė',
76563 'ę' => 'Ę',
76564 'ě' => 'Ě',
76565 'ĝ' => 'Ĝ',
76566 'ğ' => 'Ğ',
76567 'ġ' => 'Ġ',
76568 'ģ' => 'Ģ',
76569 'ĥ' => 'Ĥ',
76570 'ħ' => 'Ħ',
76571 'ĩ' => 'Ĩ',
76572 'ī' => 'Ī',
76573 'ĭ' => 'Ĭ',
76574 'į' => 'Į',
76575 'ı' => 'I',
76576 'ij' => 'IJ',
76577 'ĵ' => 'Ĵ',
76578 'ķ' => 'Ķ',
76579 'ĺ' => 'Ĺ',
76580 'ļ' => 'Ļ',
76581 'ľ' => 'Ľ',
76582 'ŀ' => 'Ŀ',
76583 'ł' => 'Ł',
76584 'ń' => 'Ń',
76585 'ņ' => 'Ņ',
76586 'ň' => 'Ň',
76587 'ŋ' => 'Ŋ',
76588 'ō' => 'Ō',
76589 'ŏ' => 'Ŏ',
76590 'ő' => 'Ő',
76591 'œ' => 'Œ',
76592 'ŕ' => 'Ŕ',
76593 'ŗ' => 'Ŗ',
76594 'ř' => 'Ř',
76595 'ś' => 'Ś',
76596 'ŝ' => 'Ŝ',
76597 'ş' => 'Ş',
76598 'š' => 'Š',
76599 'ţ' => 'Ţ',
76600 'ť' => 'Ť',
76601 'ŧ' => 'Ŧ',
76602 'ũ' => 'Ũ',
76603 'ū' => 'Ū',
76604 'ŭ' => 'Ŭ',
76605 'ů' => 'Ů',
76606 'ű' => 'Ű',
76607 'ų' => 'Ų',
76608 'ŵ' => 'Ŵ',
76609 'ŷ' => 'Ŷ',
76610 'ź' => 'Ź',
76611 'ż' => 'Ż',
76612 'ž' => 'Ž',
76613 'ſ' => 'S',
76614 'ƀ' => 'Ƀ',
76615 'ƃ' => 'Ƃ',
76616 'ƅ' => 'Ƅ',
76617 'ƈ' => 'Ƈ',
76618 'ƌ' => 'Ƌ',
76619 'ƒ' => 'Ƒ',
76620 'ƕ' => 'Ƕ',
76621 'ƙ' => 'Ƙ',
76622 'ƚ' => 'Ƚ',
76623 'ƞ' => 'Ƞ',
76624 'ơ' => 'Ơ',
76625 'ƣ' => 'Ƣ',
76626 'ƥ' => 'Ƥ',
76627 'ƨ' => 'Ƨ',
76628 'ƭ' => 'Ƭ',
76629 'ư' => 'Ư',
76630 'ƴ' => 'Ƴ',
76631 'ƶ' => 'Ƶ',
76632 'ƹ' => 'Ƹ',
76633 'ƽ' => 'Ƽ',
76634 'ƿ' => 'Ƿ',
76635 'Dž' => 'DŽ',
76636 'dž' => 'DŽ',
76637 'Lj' => 'LJ',
76638 'lj' => 'LJ',
76639 'Nj' => 'NJ',
76640 'nj' => 'NJ',
76641 'ǎ' => 'Ǎ',
76642 'ǐ' => 'Ǐ',
76643 'ǒ' => 'Ǒ',
76644 'ǔ' => 'Ǔ',
76645 'ǖ' => 'Ǖ',
76646 'ǘ' => 'Ǘ',
76647 'ǚ' => 'Ǚ',
76648 'ǜ' => 'Ǜ',
76649 'ǝ' => 'Ǝ',
76650 'ǟ' => 'Ǟ',
76651 'ǡ' => 'Ǡ',
76652 'ǣ' => 'Ǣ',
76653 'ǥ' => 'Ǥ',
76654 'ǧ' => 'Ǧ',
76655 'ǩ' => 'Ǩ',
76656 'ǫ' => 'Ǫ',
76657 'ǭ' => 'Ǭ',
76658 'ǯ' => 'Ǯ',
76659 'Dz' => 'DZ',
76660 'dz' => 'DZ',
76661 'ǵ' => 'Ǵ',
76662 'ǹ' => 'Ǹ',
76663 'ǻ' => 'Ǻ',
76664 'ǽ' => 'Ǽ',
76665 'ǿ' => 'Ǿ',
76666 'ȁ' => 'Ȁ',
76667 'ȃ' => 'Ȃ',
76668 'ȅ' => 'Ȅ',
76669 'ȇ' => 'Ȇ',
76670 'ȉ' => 'Ȉ',
76671 'ȋ' => 'Ȋ',
76672 'ȍ' => 'Ȍ',
76673 'ȏ' => 'Ȏ',
76674 'ȑ' => 'Ȑ',
76675 'ȓ' => 'Ȓ',
76676 'ȕ' => 'Ȕ',
76677 'ȗ' => 'Ȗ',
76678 'ș' => 'Ș',
76679 'ț' => 'Ț',
76680 'ȝ' => 'Ȝ',
76681 'ȟ' => 'Ȟ',
76682 'ȣ' => 'Ȣ',
76683 'ȥ' => 'Ȥ',
76684 'ȧ' => 'Ȧ',
76685 'ȩ' => 'Ȩ',
76686 'ȫ' => 'Ȫ',
76687 'ȭ' => 'Ȭ',
76688 'ȯ' => 'Ȯ',
76689 'ȱ' => 'Ȱ',
76690 'ȳ' => 'Ȳ',
76691 'ȼ' => 'Ȼ',
76692 'ȿ' => 'Ȿ',
76693 'ɀ' => 'Ɀ',
76694 'ɂ' => 'Ɂ',
76695 'ɇ' => 'Ɇ',
76696 'ɉ' => 'Ɉ',
76697 'ɋ' => 'Ɋ',
76698 'ɍ' => 'Ɍ',
76699 'ɏ' => 'Ɏ',
76700 'ɐ' => 'Ɐ',
76701 'ɑ' => 'Ɑ',
76702 'ɒ' => 'Ɒ',
76703 'ɓ' => 'Ɓ',
76704 'ɔ' => 'Ɔ',
76705 'ɖ' => 'Ɖ',
76706 'ɗ' => 'Ɗ',
76707 'ə' => 'Ə',
76708 'ɛ' => 'Ɛ',
76709 'ɜ' => 'Ɜ',
76710 'ɠ' => 'Ɠ',
76711 'ɡ' => 'Ɡ',
76712 'ɣ' => 'Ɣ',
76713 'ɥ' => 'Ɥ',
76714 'ɦ' => 'Ɦ',
76715 'ɨ' => 'Ɨ',
76716 'ɩ' => 'Ɩ',
76717 'ɪ' => 'Ɪ',
76718 'ɫ' => 'Ɫ',
76719 'ɬ' => 'Ɬ',
76720 'ɯ' => 'Ɯ',
76721 'ɱ' => 'Ɱ',
76722 'ɲ' => 'Ɲ',
76723 'ɵ' => 'Ɵ',
76724 'ɽ' => 'Ɽ',
76725 'ʀ' => 'Ʀ',
76726 'ʂ' => 'Ʂ',
76727 'ʃ' => 'Ʃ',
76728 'ʇ' => 'Ʇ',
76729 'ʈ' => 'Ʈ',
76730 'ʉ' => 'Ʉ',
76731 'ʊ' => 'Ʊ',
76732 'ʋ' => 'Ʋ',
76733 'ʌ' => 'Ʌ',
76734 'ʒ' => 'Ʒ',
76735 'ʝ' => 'Ʝ',
76736 'ʞ' => 'Ʞ',
76737 'ͅ' => 'Ι',
76738 'ͱ' => 'Ͱ',
76739 'ͳ' => 'Ͳ',
76740 'ͷ' => 'Ͷ',
76741 'ͻ' => 'Ͻ',
76742 'ͼ' => 'Ͼ',
76743 'ͽ' => 'Ͽ',
76744 'ά' => 'Ά',
76745 'έ' => 'Έ',
76746 'ή' => 'Ή',
76747 'ί' => 'Ί',
76748 'α' => 'Α',
76749 'β' => 'Β',
76750 'γ' => 'Γ',
76751 'δ' => 'Δ',
76752 'ε' => 'Ε',
76753 'ζ' => 'Ζ',
76754 'η' => 'Η',
76755 'θ' => 'Θ',
76756 'ι' => 'Ι',
76757 'κ' => 'Κ',
76758 'λ' => 'Λ',
76759 'μ' => 'Μ',
76760 'ν' => 'Ν',
76761 'ξ' => 'Ξ',
76762 'ο' => 'Ο',
76763 'π' => 'Π',
76764 'ρ' => 'Ρ',
76765 'ς' => 'Σ',
76766 'σ' => 'Σ',
76767 'τ' => 'Τ',
76768 'υ' => 'Υ',
76769 'φ' => 'Φ',
76770 'χ' => 'Χ',
76771 'ψ' => 'Ψ',
76772 'ω' => 'Ω',
76773 'ϊ' => 'Ϊ',
76774 'ϋ' => 'Ϋ',
76775 'ό' => 'Ό',
76776 'ύ' => 'Ύ',
76777 'ώ' => 'Ώ',
76778 'ϐ' => 'Β',
76779 'ϑ' => 'Θ',
76780 'ϕ' => 'Φ',
76781 'ϖ' => 'Π',
76782 'ϗ' => 'Ϗ',
76783 'ϙ' => 'Ϙ',
76784 'ϛ' => 'Ϛ',
76785 'ϝ' => 'Ϝ',
76786 'ϟ' => 'Ϟ',
76787 'ϡ' => 'Ϡ',
76788 'ϣ' => 'Ϣ',
76789 'ϥ' => 'Ϥ',
76790 'ϧ' => 'Ϧ',
76791 'ϩ' => 'Ϩ',
76792 'ϫ' => 'Ϫ',
76793 'ϭ' => 'Ϭ',
76794 'ϯ' => 'Ϯ',
76795 'ϰ' => 'Κ',
76796 'ϱ' => 'Ρ',
76797 'ϲ' => 'Ϲ',
76798 'ϳ' => 'Ϳ',
76799 'ϵ' => 'Ε',
76800 'ϸ' => 'Ϸ',
76801 'ϻ' => 'Ϻ',
76802 'а' => 'А',
76803 'б' => 'Б',
76804 'в' => 'В',
76805 'г' => 'Г',
76806 'д' => 'Д',
76807 'е' => 'Е',
76808 'ж' => 'Ж',
76809 'з' => 'З',
76810 'и' => 'И',
76811 'й' => 'Й',
76812 'к' => 'К',
76813 'л' => 'Л',
76814 'м' => 'М',
76815 'н' => 'Н',
76816 'о' => 'О',
76817 'п' => 'П',
76818 'р' => 'Р',
76819 'с' => 'С',
76820 'т' => 'Т',
76821 'у' => 'У',
76822 'ф' => 'Ф',
76823 'х' => 'Х',
76824 'ц' => 'Ц',
76825 'ч' => 'Ч',
76826 'ш' => 'Ш',
76827 'щ' => 'Щ',
76828 'ъ' => 'Ъ',
76829 'ы' => 'Ы',
76830 'ь' => 'Ь',
76831 'э' => 'Э',
76832 'ю' => 'Ю',
76833 'я' => 'Я',
76834 'ѐ' => 'Ѐ',
76835 'ё' => 'Ё',
76836 'ђ' => 'Ђ',
76837 'ѓ' => 'Ѓ',
76838 'є' => 'Є',
76839 'ѕ' => 'Ѕ',
76840 'і' => 'І',
76841 'ї' => 'Ї',
76842 'ј' => 'Ј',
76843 'љ' => 'Љ',
76844 'њ' => 'Њ',
76845 'ћ' => 'Ћ',
76846 'ќ' => 'Ќ',
76847 'ѝ' => 'Ѝ',
76848 'ў' => 'Ў',
76849 'џ' => 'Џ',
76850 'ѡ' => 'Ѡ',
76851 'ѣ' => 'Ѣ',
76852 'ѥ' => 'Ѥ',
76853 'ѧ' => 'Ѧ',
76854 'ѩ' => 'Ѩ',
76855 'ѫ' => 'Ѫ',
76856 'ѭ' => 'Ѭ',
76857 'ѯ' => 'Ѯ',
76858 'ѱ' => 'Ѱ',
76859 'ѳ' => 'Ѳ',
76860 'ѵ' => 'Ѵ',
76861 'ѷ' => 'Ѷ',
76862 'ѹ' => 'Ѹ',
76863 'ѻ' => 'Ѻ',
76864 'ѽ' => 'Ѽ',
76865 'ѿ' => 'Ѿ',
76866 'ҁ' => 'Ҁ',
76867 'ҋ' => 'Ҋ',
76868 'ҍ' => 'Ҍ',
76869 'ҏ' => 'Ҏ',
76870 'ґ' => 'Ґ',
76871 'ғ' => 'Ғ',
76872 'ҕ' => 'Ҕ',
76873 'җ' => 'Җ',
76874 'ҙ' => 'Ҙ',
76875 'қ' => 'Қ',
76876 'ҝ' => 'Ҝ',
76877 'ҟ' => 'Ҟ',
76878 'ҡ' => 'Ҡ',
76879 'ң' => 'Ң',
76880 'ҥ' => 'Ҥ',
76881 'ҧ' => 'Ҧ',
76882 'ҩ' => 'Ҩ',
76883 'ҫ' => 'Ҫ',
76884 'ҭ' => 'Ҭ',
76885 'ү' => 'Ү',
76886 'ұ' => 'Ұ',
76887 'ҳ' => 'Ҳ',
76888 'ҵ' => 'Ҵ',
76889 'ҷ' => 'Ҷ',
76890 'ҹ' => 'Ҹ',
76891 'һ' => 'Һ',
76892 'ҽ' => 'Ҽ',
76893 'ҿ' => 'Ҿ',
76894 'ӂ' => 'Ӂ',
76895 'ӄ' => 'Ӄ',
76896 'ӆ' => 'Ӆ',
76897 'ӈ' => 'Ӈ',
76898 'ӊ' => 'Ӊ',
76899 'ӌ' => 'Ӌ',
76900 'ӎ' => 'Ӎ',
76901 'ӏ' => 'Ӏ',
76902 'ӑ' => 'Ӑ',
76903 'ӓ' => 'Ӓ',
76904 'ӕ' => 'Ӕ',
76905 'ӗ' => 'Ӗ',
76906 'ә' => 'Ә',
76907 'ӛ' => 'Ӛ',
76908 'ӝ' => 'Ӝ',
76909 'ӟ' => 'Ӟ',
76910 'ӡ' => 'Ӡ',
76911 'ӣ' => 'Ӣ',
76912 'ӥ' => 'Ӥ',
76913 'ӧ' => 'Ӧ',
76914 'ө' => 'Ө',
76915 'ӫ' => 'Ӫ',
76916 'ӭ' => 'Ӭ',
76917 'ӯ' => 'Ӯ',
76918 'ӱ' => 'Ӱ',
76919 'ӳ' => 'Ӳ',
76920 'ӵ' => 'Ӵ',
76921 'ӷ' => 'Ӷ',
76922 'ӹ' => 'Ӹ',
76923 'ӻ' => 'Ӻ',
76924 'ӽ' => 'Ӽ',
76925 'ӿ' => 'Ӿ',
76926 'ԁ' => 'Ԁ',
76927 'ԃ' => 'Ԃ',
76928 'ԅ' => 'Ԅ',
76929 'ԇ' => 'Ԇ',
76930 'ԉ' => 'Ԉ',
76931 'ԋ' => 'Ԋ',
76932 'ԍ' => 'Ԍ',
76933 'ԏ' => 'Ԏ',
76934 'ԑ' => 'Ԑ',
76935 'ԓ' => 'Ԓ',
76936 'ԕ' => 'Ԕ',
76937 'ԗ' => 'Ԗ',
76938 'ԙ' => 'Ԙ',
76939 'ԛ' => 'Ԛ',
76940 'ԝ' => 'Ԝ',
76941 'ԟ' => 'Ԟ',
76942 'ԡ' => 'Ԡ',
76943 'ԣ' => 'Ԣ',
76944 'ԥ' => 'Ԥ',
76945 'ԧ' => 'Ԧ',
76946 'ԩ' => 'Ԩ',
76947 'ԫ' => 'Ԫ',
76948 'ԭ' => 'Ԭ',
76949 'ԯ' => 'Ԯ',
76950 'ա' => 'Ա',
76951 'բ' => 'Բ',
76952 'գ' => 'Գ',
76953 'դ' => 'Դ',
76954 'ե' => 'Ե',
76955 'զ' => 'Զ',
76956 'է' => 'Է',
76957 'ը' => 'Ը',
76958 'թ' => 'Թ',
76959 'ժ' => 'Ժ',
76960 'ի' => 'Ի',
76961 'լ' => 'Լ',
76962 'խ' => 'Խ',
76963 'ծ' => 'Ծ',
76964 'կ' => 'Կ',
76965 'հ' => 'Հ',
76966 'ձ' => 'Ձ',
76967 'ղ' => 'Ղ',
76968 'ճ' => 'Ճ',
76969 'մ' => 'Մ',
76970 'յ' => 'Յ',
76971 'ն' => 'Ն',
76972 'շ' => 'Շ',
76973 'ո' => 'Ո',
76974 'չ' => 'Չ',
76975 'պ' => 'Պ',
76976 'ջ' => 'Ջ',
76977 'ռ' => 'Ռ',
76978 'ս' => 'Ս',
76979 'վ' => 'Վ',
76980 'տ' => 'Տ',
76981 'ր' => 'Ր',
76982 'ց' => 'Ց',
76983 'ւ' => 'Ւ',
76984 'փ' => 'Փ',
76985 'ք' => 'Ք',
76986 'օ' => 'Օ',
76987 'ֆ' => 'Ֆ',
76988 'ა' => 'Ა',
76989 'ბ' => 'Ბ',
76990 'გ' => 'Გ',
76991 'დ' => 'Დ',
76992 'ე' => 'Ე',
76993 'ვ' => 'Ვ',
76994 'ზ' => 'Ზ',
76995 'თ' => 'Თ',
76996 'ი' => 'Ი',
76997 'კ' => 'Კ',
76998 'ლ' => 'Ლ',
76999 'მ' => 'Მ',
77000 'ნ' => 'Ნ',
77001 'ო' => 'Ო',
77002 'პ' => 'Პ',
77003 'ჟ' => 'Ჟ',
77004 'რ' => 'Რ',
77005 'ს' => 'Ს',
77006 'ტ' => 'Ტ',
77007 'უ' => 'Უ',
77008 'ფ' => 'Ფ',
77009 'ქ' => 'Ქ',
77010 'ღ' => 'Ღ',
77011 'ყ' => 'Ყ',
77012 'შ' => 'Შ',
77013 'ჩ' => 'Ჩ',
77014 'ც' => 'Ც',
77015 'ძ' => 'Ძ',
77016 'წ' => 'Წ',
77017 'ჭ' => 'Ჭ',
77018 'ხ' => 'Ხ',
77019 'ჯ' => 'Ჯ',
77020 'ჰ' => 'Ჰ',
77021 'ჱ' => 'Ჱ',
77022 'ჲ' => 'Ჲ',
77023 'ჳ' => 'Ჳ',
77024 'ჴ' => 'Ჴ',
77025 'ჵ' => 'Ჵ',
77026 'ჶ' => 'Ჶ',
77027 'ჷ' => 'Ჷ',
77028 'ჸ' => 'Ჸ',
77029 'ჹ' => 'Ჹ',
77030 'ჺ' => 'Ჺ',
77031 'ჽ' => 'Ჽ',
77032 'ჾ' => 'Ჾ',
77033 'ჿ' => 'Ჿ',
77034 'ᏸ' => 'Ᏸ',
77035 'ᏹ' => 'Ᏹ',
77036 'ᏺ' => 'Ᏺ',
77037 'ᏻ' => 'Ᏻ',
77038 'ᏼ' => 'Ᏼ',
77039 'ᏽ' => 'Ᏽ',
77040 'ᲀ' => 'В',
77041 'ᲁ' => 'Д',
77042 'ᲂ' => 'О',
77043 'ᲃ' => 'С',
77044 'ᲄ' => 'Т',
77045 'ᲅ' => 'Т',
77046 'ᲆ' => 'Ъ',
77047 'ᲇ' => 'Ѣ',
77048 'ᲈ' => 'Ꙋ',
77049 'ᵹ' => 'Ᵹ',
77050 'ᵽ' => 'Ᵽ',
77051 'ᶎ' => 'Ᶎ',
77052 'ḁ' => 'Ḁ',
77053 'ḃ' => 'Ḃ',
77054 'ḅ' => 'Ḅ',
77055 'ḇ' => 'Ḇ',
77056 'ḉ' => 'Ḉ',
77057 'ḋ' => 'Ḋ',
77058 'ḍ' => 'Ḍ',
77059 'ḏ' => 'Ḏ',
77060 'ḑ' => 'Ḑ',
77061 'ḓ' => 'Ḓ',
77062 'ḕ' => 'Ḕ',
77063 'ḗ' => 'Ḗ',
77064 'ḙ' => 'Ḙ',
77065 'ḛ' => 'Ḛ',
77066 'ḝ' => 'Ḝ',
77067 'ḟ' => 'Ḟ',
77068 'ḡ' => 'Ḡ',
77069 'ḣ' => 'Ḣ',
77070 'ḥ' => 'Ḥ',
77071 'ḧ' => 'Ḧ',
77072 'ḩ' => 'Ḩ',
77073 'ḫ' => 'Ḫ',
77074 'ḭ' => 'Ḭ',
77075 'ḯ' => 'Ḯ',
77076 'ḱ' => 'Ḱ',
77077 'ḳ' => 'Ḳ',
77078 'ḵ' => 'Ḵ',
77079 'ḷ' => 'Ḷ',
77080 'ḹ' => 'Ḹ',
77081 'ḻ' => 'Ḻ',
77082 'ḽ' => 'Ḽ',
77083 'ḿ' => 'Ḿ',
77084 'ṁ' => 'Ṁ',
77085 'ṃ' => 'Ṃ',
77086 'ṅ' => 'Ṅ',
77087 'ṇ' => 'Ṇ',
77088 'ṉ' => 'Ṉ',
77089 'ṋ' => 'Ṋ',
77090 'ṍ' => 'Ṍ',
77091 'ṏ' => 'Ṏ',
77092 'ṑ' => 'Ṑ',
77093 'ṓ' => 'Ṓ',
77094 'ṕ' => 'Ṕ',
77095 'ṗ' => 'Ṗ',
77096 'ṙ' => 'Ṙ',
77097 'ṛ' => 'Ṛ',
77098 'ṝ' => 'Ṝ',
77099 'ṟ' => 'Ṟ',
77100 'ṡ' => 'Ṡ',
77101 'ṣ' => 'Ṣ',
77102 'ṥ' => 'Ṥ',
77103 'ṧ' => 'Ṧ',
77104 'ṩ' => 'Ṩ',
77105 'ṫ' => 'Ṫ',
77106 'ṭ' => 'Ṭ',
77107 'ṯ' => 'Ṯ',
77108 'ṱ' => 'Ṱ',
77109 'ṳ' => 'Ṳ',
77110 'ṵ' => 'Ṵ',
77111 'ṷ' => 'Ṷ',
77112 'ṹ' => 'Ṹ',
77113 'ṻ' => 'Ṻ',
77114 'ṽ' => 'Ṽ',
77115 'ṿ' => 'Ṿ',
77116 'ẁ' => 'Ẁ',
77117 'ẃ' => 'Ẃ',
77118 'ẅ' => 'Ẅ',
77119 'ẇ' => 'Ẇ',
77120 'ẉ' => 'Ẉ',
77121 'ẋ' => 'Ẋ',
77122 'ẍ' => 'Ẍ',
77123 'ẏ' => 'Ẏ',
77124 'ẑ' => 'Ẑ',
77125 'ẓ' => 'Ẓ',
77126 'ẕ' => 'Ẕ',
77127 'ẛ' => 'Ṡ',
77128 'ạ' => 'Ạ',
77129 'ả' => 'Ả',
77130 'ấ' => 'Ấ',
77131 'ầ' => 'Ầ',
77132 'ẩ' => 'Ẩ',
77133 'ẫ' => 'Ẫ',
77134 'ậ' => 'Ậ',
77135 'ắ' => 'Ắ',
77136 'ằ' => 'Ằ',
77137 'ẳ' => 'Ẳ',
77138 'ẵ' => 'Ẵ',
77139 'ặ' => 'Ặ',
77140 'ẹ' => 'Ẹ',
77141 'ẻ' => 'Ẻ',
77142 'ẽ' => 'Ẽ',
77143 'ế' => 'Ế',
77144 'ề' => 'Ề',
77145 'ể' => 'Ể',
77146 'ễ' => 'Ễ',
77147 'ệ' => 'Ệ',
77148 'ỉ' => 'Ỉ',
77149 'ị' => 'Ị',
77150 'ọ' => 'Ọ',
77151 'ỏ' => 'Ỏ',
77152 'ố' => 'Ố',
77153 'ồ' => 'Ồ',
77154 'ổ' => 'Ổ',
77155 'ỗ' => 'Ỗ',
77156 'ộ' => 'Ộ',
77157 'ớ' => 'Ớ',
77158 'ờ' => 'Ờ',
77159 'ở' => 'Ở',
77160 'ỡ' => 'Ỡ',
77161 'ợ' => 'Ợ',
77162 'ụ' => 'Ụ',
77163 'ủ' => 'Ủ',
77164 'ứ' => 'Ứ',
77165 'ừ' => 'Ừ',
77166 'ử' => 'Ử',
77167 'ữ' => 'Ữ',
77168 'ự' => 'Ự',
77169 'ỳ' => 'Ỳ',
77170 'ỵ' => 'Ỵ',
77171 'ỷ' => 'Ỷ',
77172 'ỹ' => 'Ỹ',
77173 'ỻ' => 'Ỻ',
77174 'ỽ' => 'Ỽ',
77175 'ỿ' => 'Ỿ',
77176 'ἀ' => 'Ἀ',
77177 'ἁ' => 'Ἁ',
77178 'ἂ' => 'Ἂ',
77179 'ἃ' => 'Ἃ',
77180 'ἄ' => 'Ἄ',
77181 'ἅ' => 'Ἅ',
77182 'ἆ' => 'Ἆ',
77183 'ἇ' => 'Ἇ',
77184 'ἐ' => 'Ἐ',
77185 'ἑ' => 'Ἑ',
77186 'ἒ' => 'Ἒ',
77187 'ἓ' => 'Ἓ',
77188 'ἔ' => 'Ἔ',
77189 'ἕ' => 'Ἕ',
77190 'ἠ' => 'Ἠ',
77191 'ἡ' => 'Ἡ',
77192 'ἢ' => 'Ἢ',
77193 'ἣ' => 'Ἣ',
77194 'ἤ' => 'Ἤ',
77195 'ἥ' => 'Ἥ',
77196 'ἦ' => 'Ἦ',
77197 'ἧ' => 'Ἧ',
77198 'ἰ' => 'Ἰ',
77199 'ἱ' => 'Ἱ',
77200 'ἲ' => 'Ἲ',
77201 'ἳ' => 'Ἳ',
77202 'ἴ' => 'Ἴ',
77203 'ἵ' => 'Ἵ',
77204 'ἶ' => 'Ἶ',
77205 'ἷ' => 'Ἷ',
77206 'ὀ' => 'Ὀ',
77207 'ὁ' => 'Ὁ',
77208 'ὂ' => 'Ὂ',
77209 'ὃ' => 'Ὃ',
77210 'ὄ' => 'Ὄ',
77211 'ὅ' => 'Ὅ',
77212 'ὑ' => 'Ὑ',
77213 'ὓ' => 'Ὓ',
77214 'ὕ' => 'Ὕ',
77215 'ὗ' => 'Ὗ',
77216 'ὠ' => 'Ὠ',
77217 'ὡ' => 'Ὡ',
77218 'ὢ' => 'Ὢ',
77219 'ὣ' => 'Ὣ',
77220 'ὤ' => 'Ὤ',
77221 'ὥ' => 'Ὥ',
77222 'ὦ' => 'Ὦ',
77223 'ὧ' => 'Ὧ',
77224 'ὰ' => 'Ὰ',
77225 'ά' => 'Ά',
77226 'ὲ' => 'Ὲ',
77227 'έ' => 'Έ',
77228 'ὴ' => 'Ὴ',
77229 'ή' => 'Ή',
77230 'ὶ' => 'Ὶ',
77231 'ί' => 'Ί',
77232 'ὸ' => 'Ὸ',
77233 'ό' => 'Ό',
77234 'ὺ' => 'Ὺ',
77235 'ύ' => 'Ύ',
77236 'ὼ' => 'Ὼ',
77237 'ώ' => 'Ώ',
77238 'ᾀ' => 'ᾈ',
77239 'ᾁ' => 'ᾉ',
77240 'ᾂ' => 'ᾊ',
77241 'ᾃ' => 'ᾋ',
77242 'ᾄ' => 'ᾌ',
77243 'ᾅ' => 'ᾍ',
77244 'ᾆ' => 'ᾎ',
77245 'ᾇ' => 'ᾏ',
77246 'ᾐ' => 'ᾘ',
77247 'ᾑ' => 'ᾙ',
77248 'ᾒ' => 'ᾚ',
77249 'ᾓ' => 'ᾛ',
77250 'ᾔ' => 'ᾜ',
77251 'ᾕ' => 'ᾝ',
77252 'ᾖ' => 'ᾞ',
77253 'ᾗ' => 'ᾟ',
77254 'ᾠ' => 'ᾨ',
77255 'ᾡ' => 'ᾩ',
77256 'ᾢ' => 'ᾪ',
77257 'ᾣ' => 'ᾫ',
77258 'ᾤ' => 'ᾬ',
77259 'ᾥ' => 'ᾭ',
77260 'ᾦ' => 'ᾮ',
77261 'ᾧ' => 'ᾯ',
77262 'ᾰ' => 'Ᾰ',
77263 'ᾱ' => 'Ᾱ',
77264 'ᾳ' => 'ᾼ',
77265 'ι' => 'Ι',
77266 'ῃ' => 'ῌ',
77267 'ῐ' => 'Ῐ',
77268 'ῑ' => 'Ῑ',
77269 'ῠ' => 'Ῠ',
77270 'ῡ' => 'Ῡ',
77271 'ῥ' => 'Ῥ',
77272 'ῳ' => 'ῼ',
77273 'ⅎ' => 'Ⅎ',
77274 'ⅰ' => 'Ⅰ',
77275 'ⅱ' => 'Ⅱ',
77276 'ⅲ' => 'Ⅲ',
77277 'ⅳ' => 'Ⅳ',
77278 'ⅴ' => 'Ⅴ',
77279 'ⅵ' => 'Ⅵ',
77280 'ⅶ' => 'Ⅶ',
77281 'ⅷ' => 'Ⅷ',
77282 'ⅸ' => 'Ⅸ',
77283 'ⅹ' => 'Ⅹ',
77284 'ⅺ' => 'Ⅺ',
77285 'ⅻ' => 'Ⅻ',
77286 'ⅼ' => 'Ⅼ',
77287 'ⅽ' => 'Ⅽ',
77288 'ⅾ' => 'Ⅾ',
77289 'ⅿ' => 'Ⅿ',
77290 'ↄ' => 'Ↄ',
77291 'ⓐ' => 'Ⓐ',
77292 'ⓑ' => 'Ⓑ',
77293 'ⓒ' => 'Ⓒ',
77294 'ⓓ' => 'Ⓓ',
77295 'ⓔ' => 'Ⓔ',
77296 'ⓕ' => 'Ⓕ',
77297 'ⓖ' => 'Ⓖ',
77298 'ⓗ' => 'Ⓗ',
77299 'ⓘ' => 'Ⓘ',
77300 'ⓙ' => 'Ⓙ',
77301 'ⓚ' => 'Ⓚ',
77302 'ⓛ' => 'Ⓛ',
77303 'ⓜ' => 'Ⓜ',
77304 'ⓝ' => 'Ⓝ',
77305 'ⓞ' => 'Ⓞ',
77306 'ⓟ' => 'Ⓟ',
77307 'ⓠ' => 'Ⓠ',
77308 'ⓡ' => 'Ⓡ',
77309 'ⓢ' => 'Ⓢ',
77310 'ⓣ' => 'Ⓣ',
77311 'ⓤ' => 'Ⓤ',
77312 'ⓥ' => 'Ⓥ',
77313 'ⓦ' => 'Ⓦ',
77314 'ⓧ' => 'Ⓧ',
77315 'ⓨ' => 'Ⓨ',
77316 'ⓩ' => 'Ⓩ',
77317 'ⰰ' => 'Ⰰ',
77318 'ⰱ' => 'Ⰱ',
77319 'ⰲ' => 'Ⰲ',
77320 'ⰳ' => 'Ⰳ',
77321 'ⰴ' => 'Ⰴ',
77322 'ⰵ' => 'Ⰵ',
77323 'ⰶ' => 'Ⰶ',
77324 'ⰷ' => 'Ⰷ',
77325 'ⰸ' => 'Ⰸ',
77326 'ⰹ' => 'Ⰹ',
77327 'ⰺ' => 'Ⰺ',
77328 'ⰻ' => 'Ⰻ',
77329 'ⰼ' => 'Ⰼ',
77330 'ⰽ' => 'Ⰽ',
77331 'ⰾ' => 'Ⰾ',
77332 'ⰿ' => 'Ⰿ',
77333 'ⱀ' => 'Ⱀ',
77334 'ⱁ' => 'Ⱁ',
77335 'ⱂ' => 'Ⱂ',
77336 'ⱃ' => 'Ⱃ',
77337 'ⱄ' => 'Ⱄ',
77338 'ⱅ' => 'Ⱅ',
77339 'ⱆ' => 'Ⱆ',
77340 'ⱇ' => 'Ⱇ',
77341 'ⱈ' => 'Ⱈ',
77342 'ⱉ' => 'Ⱉ',
77343 'ⱊ' => 'Ⱊ',
77344 'ⱋ' => 'Ⱋ',
77345 'ⱌ' => 'Ⱌ',
77346 'ⱍ' => 'Ⱍ',
77347 'ⱎ' => 'Ⱎ',
77348 'ⱏ' => 'Ⱏ',
77349 'ⱐ' => 'Ⱐ',
77350 'ⱑ' => 'Ⱑ',
77351 'ⱒ' => 'Ⱒ',
77352 'ⱓ' => 'Ⱓ',
77353 'ⱔ' => 'Ⱔ',
77354 'ⱕ' => 'Ⱕ',
77355 'ⱖ' => 'Ⱖ',
77356 'ⱗ' => 'Ⱗ',
77357 'ⱘ' => 'Ⱘ',
77358 'ⱙ' => 'Ⱙ',
77359 'ⱚ' => 'Ⱚ',
77360 'ⱛ' => 'Ⱛ',
77361 'ⱜ' => 'Ⱜ',
77362 'ⱝ' => 'Ⱝ',
77363 'ⱞ' => 'Ⱞ',
77364 'ⱡ' => 'Ⱡ',
77365 'ⱥ' => 'Ⱥ',
77366 'ⱦ' => 'Ⱦ',
77367 'ⱨ' => 'Ⱨ',
77368 'ⱪ' => 'Ⱪ',
77369 'ⱬ' => 'Ⱬ',
77370 'ⱳ' => 'Ⱳ',
77371 'ⱶ' => 'Ⱶ',
77372 'ⲁ' => 'Ⲁ',
77373 'ⲃ' => 'Ⲃ',
77374 'ⲅ' => 'Ⲅ',
77375 'ⲇ' => 'Ⲇ',
77376 'ⲉ' => 'Ⲉ',
77377 'ⲋ' => 'Ⲋ',
77378 'ⲍ' => 'Ⲍ',
77379 'ⲏ' => 'Ⲏ',
77380 'ⲑ' => 'Ⲑ',
77381 'ⲓ' => 'Ⲓ',
77382 'ⲕ' => 'Ⲕ',
77383 'ⲗ' => 'Ⲗ',
77384 'ⲙ' => 'Ⲙ',
77385 'ⲛ' => 'Ⲛ',
77386 'ⲝ' => 'Ⲝ',
77387 'ⲟ' => 'Ⲟ',
77388 'ⲡ' => 'Ⲡ',
77389 'ⲣ' => 'Ⲣ',
77390 'ⲥ' => 'Ⲥ',
77391 'ⲧ' => 'Ⲧ',
77392 'ⲩ' => 'Ⲩ',
77393 'ⲫ' => 'Ⲫ',
77394 'ⲭ' => 'Ⲭ',
77395 'ⲯ' => 'Ⲯ',
77396 'ⲱ' => 'Ⲱ',
77397 'ⲳ' => 'Ⲳ',
77398 'ⲵ' => 'Ⲵ',
77399 'ⲷ' => 'Ⲷ',
77400 'ⲹ' => 'Ⲹ',
77401 'ⲻ' => 'Ⲻ',
77402 'ⲽ' => 'Ⲽ',
77403 'ⲿ' => 'Ⲿ',
77404 'ⳁ' => 'Ⳁ',
77405 'ⳃ' => 'Ⳃ',
77406 'ⳅ' => 'Ⳅ',
77407 'ⳇ' => 'Ⳇ',
77408 'ⳉ' => 'Ⳉ',
77409 'ⳋ' => 'Ⳋ',
77410 'ⳍ' => 'Ⳍ',
77411 'ⳏ' => 'Ⳏ',
77412 'ⳑ' => 'Ⳑ',
77413 'ⳓ' => 'Ⳓ',
77414 'ⳕ' => 'Ⳕ',
77415 'ⳗ' => 'Ⳗ',
77416 'ⳙ' => 'Ⳙ',
77417 'ⳛ' => 'Ⳛ',
77418 'ⳝ' => 'Ⳝ',
77419 'ⳟ' => 'Ⳟ',
77420 'ⳡ' => 'Ⳡ',
77421 'ⳣ' => 'Ⳣ',
77422 'ⳬ' => 'Ⳬ',
77423 'ⳮ' => 'Ⳮ',
77424 'ⳳ' => 'Ⳳ',
77425 'ⴀ' => 'Ⴀ',
77426 'ⴁ' => 'Ⴁ',
77427 'ⴂ' => 'Ⴂ',
77428 'ⴃ' => 'Ⴃ',
77429 'ⴄ' => 'Ⴄ',
77430 'ⴅ' => 'Ⴅ',
77431 'ⴆ' => 'Ⴆ',
77432 'ⴇ' => 'Ⴇ',
77433 'ⴈ' => 'Ⴈ',
77434 'ⴉ' => 'Ⴉ',
77435 'ⴊ' => 'Ⴊ',
77436 'ⴋ' => 'Ⴋ',
77437 'ⴌ' => 'Ⴌ',
77438 'ⴍ' => 'Ⴍ',
77439 'ⴎ' => 'Ⴎ',
77440 'ⴏ' => 'Ⴏ',
77441 'ⴐ' => 'Ⴐ',
77442 'ⴑ' => 'Ⴑ',
77443 'ⴒ' => 'Ⴒ',
77444 'ⴓ' => 'Ⴓ',
77445 'ⴔ' => 'Ⴔ',
77446 'ⴕ' => 'Ⴕ',
77447 'ⴖ' => 'Ⴖ',
77448 'ⴗ' => 'Ⴗ',
77449 'ⴘ' => 'Ⴘ',
77450 'ⴙ' => 'Ⴙ',
77451 'ⴚ' => 'Ⴚ',
77452 'ⴛ' => 'Ⴛ',
77453 'ⴜ' => 'Ⴜ',
77454 'ⴝ' => 'Ⴝ',
77455 'ⴞ' => 'Ⴞ',
77456 'ⴟ' => 'Ⴟ',
77457 'ⴠ' => 'Ⴠ',
77458 'ⴡ' => 'Ⴡ',
77459 'ⴢ' => 'Ⴢ',
77460 'ⴣ' => 'Ⴣ',
77461 'ⴤ' => 'Ⴤ',
77462 'ⴥ' => 'Ⴥ',
77463 'ⴧ' => 'Ⴧ',
77464 'ⴭ' => 'Ⴭ',
77465 'ꙁ' => 'Ꙁ',
77466 'ꙃ' => 'Ꙃ',
77467 'ꙅ' => 'Ꙅ',
77468 'ꙇ' => 'Ꙇ',
77469 'ꙉ' => 'Ꙉ',
77470 'ꙋ' => 'Ꙋ',
77471 'ꙍ' => 'Ꙍ',
77472 'ꙏ' => 'Ꙏ',
77473 'ꙑ' => 'Ꙑ',
77474 'ꙓ' => 'Ꙓ',
77475 'ꙕ' => 'Ꙕ',
77476 'ꙗ' => 'Ꙗ',
77477 'ꙙ' => 'Ꙙ',
77478 'ꙛ' => 'Ꙛ',
77479 'ꙝ' => 'Ꙝ',
77480 'ꙟ' => 'Ꙟ',
77481 'ꙡ' => 'Ꙡ',
77482 'ꙣ' => 'Ꙣ',
77483 'ꙥ' => 'Ꙥ',
77484 'ꙧ' => 'Ꙧ',
77485 'ꙩ' => 'Ꙩ',
77486 'ꙫ' => 'Ꙫ',
77487 'ꙭ' => 'Ꙭ',
77488 'ꚁ' => 'Ꚁ',
77489 'ꚃ' => 'Ꚃ',
77490 'ꚅ' => 'Ꚅ',
77491 'ꚇ' => 'Ꚇ',
77492 'ꚉ' => 'Ꚉ',
77493 'ꚋ' => 'Ꚋ',
77494 'ꚍ' => 'Ꚍ',
77495 'ꚏ' => 'Ꚏ',
77496 'ꚑ' => 'Ꚑ',
77497 'ꚓ' => 'Ꚓ',
77498 'ꚕ' => 'Ꚕ',
77499 'ꚗ' => 'Ꚗ',
77500 'ꚙ' => 'Ꚙ',
77501 'ꚛ' => 'Ꚛ',
77502 'ꜣ' => 'Ꜣ',
77503 'ꜥ' => 'Ꜥ',
77504 'ꜧ' => 'Ꜧ',
77505 'ꜩ' => 'Ꜩ',
77506 'ꜫ' => 'Ꜫ',
77507 'ꜭ' => 'Ꜭ',
77508 'ꜯ' => 'Ꜯ',
77509 'ꜳ' => 'Ꜳ',
77510 'ꜵ' => 'Ꜵ',
77511 'ꜷ' => 'Ꜷ',
77512 'ꜹ' => 'Ꜹ',
77513 'ꜻ' => 'Ꜻ',
77514 'ꜽ' => 'Ꜽ',
77515 'ꜿ' => 'Ꜿ',
77516 'ꝁ' => 'Ꝁ',
77517 'ꝃ' => 'Ꝃ',
77518 'ꝅ' => 'Ꝅ',
77519 'ꝇ' => 'Ꝇ',
77520 'ꝉ' => 'Ꝉ',
77521 'ꝋ' => 'Ꝋ',
77522 'ꝍ' => 'Ꝍ',
77523 'ꝏ' => 'Ꝏ',
77524 'ꝑ' => 'Ꝑ',
77525 'ꝓ' => 'Ꝓ',
77526 'ꝕ' => 'Ꝕ',
77527 'ꝗ' => 'Ꝗ',
77528 'ꝙ' => 'Ꝙ',
77529 'ꝛ' => 'Ꝛ',
77530 'ꝝ' => 'Ꝝ',
77531 'ꝟ' => 'Ꝟ',
77532 'ꝡ' => 'Ꝡ',
77533 'ꝣ' => 'Ꝣ',
77534 'ꝥ' => 'Ꝥ',
77535 'ꝧ' => 'Ꝧ',
77536 'ꝩ' => 'Ꝩ',
77537 'ꝫ' => 'Ꝫ',
77538 'ꝭ' => 'Ꝭ',
77539 'ꝯ' => 'Ꝯ',
77540 'ꝺ' => 'Ꝺ',
77541 'ꝼ' => 'Ꝼ',
77542 'ꝿ' => 'Ꝿ',
77543 'ꞁ' => 'Ꞁ',
77544 'ꞃ' => 'Ꞃ',
77545 'ꞅ' => 'Ꞅ',
77546 'ꞇ' => 'Ꞇ',
77547 'ꞌ' => 'Ꞌ',
77548 'ꞑ' => 'Ꞑ',
77549 'ꞓ' => 'Ꞓ',
77550 'ꞔ' => 'Ꞔ',
77551 'ꞗ' => 'Ꞗ',
77552 'ꞙ' => 'Ꞙ',
77553 'ꞛ' => 'Ꞛ',
77554 'ꞝ' => 'Ꞝ',
77555 'ꞟ' => 'Ꞟ',
77556 'ꞡ' => 'Ꞡ',
77557 'ꞣ' => 'Ꞣ',
77558 'ꞥ' => 'Ꞥ',
77559 'ꞧ' => 'Ꞧ',
77560 'ꞩ' => 'Ꞩ',
77561 'ꞵ' => 'Ꞵ',
77562 'ꞷ' => 'Ꞷ',
77563 'ꞹ' => 'Ꞹ',
77564 'ꞻ' => 'Ꞻ',
77565 'ꞽ' => 'Ꞽ',
77566 'ꞿ' => 'Ꞿ',
77567 'ꟃ' => 'Ꟃ',
77568 'ꟈ' => 'Ꟈ',
77569 'ꟊ' => 'Ꟊ',
77570 'ꟶ' => 'Ꟶ',
77571 'ꭓ' => 'Ꭓ',
77572 'ꭰ' => 'Ꭰ',
77573 'ꭱ' => 'Ꭱ',
77574 'ꭲ' => 'Ꭲ',
77575 'ꭳ' => 'Ꭳ',
77576 'ꭴ' => 'Ꭴ',
77577 'ꭵ' => 'Ꭵ',
77578 'ꭶ' => 'Ꭶ',
77579 'ꭷ' => 'Ꭷ',
77580 'ꭸ' => 'Ꭸ',
77581 'ꭹ' => 'Ꭹ',
77582 'ꭺ' => 'Ꭺ',
77583 'ꭻ' => 'Ꭻ',
77584 'ꭼ' => 'Ꭼ',
77585 'ꭽ' => 'Ꭽ',
77586 'ꭾ' => 'Ꭾ',
77587 'ꭿ' => 'Ꭿ',
77588 'ꮀ' => 'Ꮀ',
77589 'ꮁ' => 'Ꮁ',
77590 'ꮂ' => 'Ꮂ',
77591 'ꮃ' => 'Ꮃ',
77592 'ꮄ' => 'Ꮄ',
77593 'ꮅ' => 'Ꮅ',
77594 'ꮆ' => 'Ꮆ',
77595 'ꮇ' => 'Ꮇ',
77596 'ꮈ' => 'Ꮈ',
77597 'ꮉ' => 'Ꮉ',
77598 'ꮊ' => 'Ꮊ',
77599 'ꮋ' => 'Ꮋ',
77600 'ꮌ' => 'Ꮌ',
77601 'ꮍ' => 'Ꮍ',
77602 'ꮎ' => 'Ꮎ',
77603 'ꮏ' => 'Ꮏ',
77604 'ꮐ' => 'Ꮐ',
77605 'ꮑ' => 'Ꮑ',
77606 'ꮒ' => 'Ꮒ',
77607 'ꮓ' => 'Ꮓ',
77608 'ꮔ' => 'Ꮔ',
77609 'ꮕ' => 'Ꮕ',
77610 'ꮖ' => 'Ꮖ',
77611 'ꮗ' => 'Ꮗ',
77612 'ꮘ' => 'Ꮘ',
77613 'ꮙ' => 'Ꮙ',
77614 'ꮚ' => 'Ꮚ',
77615 'ꮛ' => 'Ꮛ',
77616 'ꮜ' => 'Ꮜ',
77617 'ꮝ' => 'Ꮝ',
77618 'ꮞ' => 'Ꮞ',
77619 'ꮟ' => 'Ꮟ',
77620 'ꮠ' => 'Ꮠ',
77621 'ꮡ' => 'Ꮡ',
77622 'ꮢ' => 'Ꮢ',
77623 'ꮣ' => 'Ꮣ',
77624 'ꮤ' => 'Ꮤ',
77625 'ꮥ' => 'Ꮥ',
77626 'ꮦ' => 'Ꮦ',
77627 'ꮧ' => 'Ꮧ',
77628 'ꮨ' => 'Ꮨ',
77629 'ꮩ' => 'Ꮩ',
77630 'ꮪ' => 'Ꮪ',
77631 'ꮫ' => 'Ꮫ',
77632 'ꮬ' => 'Ꮬ',
77633 'ꮭ' => 'Ꮭ',
77634 'ꮮ' => 'Ꮮ',
77635 'ꮯ' => 'Ꮯ',
77636 'ꮰ' => 'Ꮰ',
77637 'ꮱ' => 'Ꮱ',
77638 'ꮲ' => 'Ꮲ',
77639 'ꮳ' => 'Ꮳ',
77640 'ꮴ' => 'Ꮴ',
77641 'ꮵ' => 'Ꮵ',
77642 'ꮶ' => 'Ꮶ',
77643 'ꮷ' => 'Ꮷ',
77644 'ꮸ' => 'Ꮸ',
77645 'ꮹ' => 'Ꮹ',
77646 'ꮺ' => 'Ꮺ',
77647 'ꮻ' => 'Ꮻ',
77648 'ꮼ' => 'Ꮼ',
77649 'ꮽ' => 'Ꮽ',
77650 'ꮾ' => 'Ꮾ',
77651 'ꮿ' => 'Ꮿ',
77652 'a' => 'A',
77653 'b' => 'B',
77654 'c' => 'C',
77655 'd' => 'D',
77656 'e' => 'E',
77657 'f' => 'F',
77658 'g' => 'G',
77659 'h' => 'H',
77660 'i' => 'I',
77661 'j' => 'J',
77662 'k' => 'K',
77663 'l' => 'L',
77664 'm' => 'M',
77665 'n' => 'N',
77666 'o' => 'O',
77667 'p' => 'P',
77668 'q' => 'Q',
77669 'r' => 'R',
77670 's' => 'S',
77671 't' => 'T',
77672 'u' => 'U',
77673 'v' => 'V',
77674 'w' => 'W',
77675 'x' => 'X',
77676 'y' => 'Y',
77677 'z' => 'Z',
77678 '𐐨' => '𐐀',
77679 '𐐩' => '𐐁',
77680 '𐐪' => '𐐂',
77681 '𐐫' => '𐐃',
77682 '𐐬' => '𐐄',
77683 '𐐭' => '𐐅',
77684 '𐐮' => '𐐆',
77685 '𐐯' => '𐐇',
77686 '𐐰' => '𐐈',
77687 '𐐱' => '𐐉',
77688 '𐐲' => '𐐊',
77689 '𐐳' => '𐐋',
77690 '𐐴' => '𐐌',
77691 '𐐵' => '𐐍',
77692 '𐐶' => '𐐎',
77693 '𐐷' => '𐐏',
77694 '𐐸' => '𐐐',
77695 '𐐹' => '𐐑',
77696 '𐐺' => '𐐒',
77697 '𐐻' => '𐐓',
77698 '𐐼' => '𐐔',
77699 '𐐽' => '𐐕',
77700 '𐐾' => '𐐖',
77701 '𐐿' => '𐐗',
77702 '𐑀' => '𐐘',
77703 '𐑁' => '𐐙',
77704 '𐑂' => '𐐚',
77705 '𐑃' => '𐐛',
77706 '𐑄' => '𐐜',
77707 '𐑅' => '𐐝',
77708 '𐑆' => '𐐞',
77709 '𐑇' => '𐐟',
77710 '𐑈' => '𐐠',
77711 '𐑉' => '𐐡',
77712 '𐑊' => '𐐢',
77713 '𐑋' => '𐐣',
77714 '𐑌' => '𐐤',
77715 '𐑍' => '𐐥',
77716 '𐑎' => '𐐦',
77717 '𐑏' => '𐐧',
77718 '𐓘' => '𐒰',
77719 '𐓙' => '𐒱',
77720 '𐓚' => '𐒲',
77721 '𐓛' => '𐒳',
77722 '𐓜' => '𐒴',
77723 '𐓝' => '𐒵',
77724 '𐓞' => '𐒶',
77725 '𐓟' => '𐒷',
77726 '𐓠' => '𐒸',
77727 '𐓡' => '𐒹',
77728 '𐓢' => '𐒺',
77729 '𐓣' => '𐒻',
77730 '𐓤' => '𐒼',
77731 '𐓥' => '𐒽',
77732 '𐓦' => '𐒾',
77733 '𐓧' => '𐒿',
77734 '𐓨' => '𐓀',
77735 '𐓩' => '𐓁',
77736 '𐓪' => '𐓂',
77737 '𐓫' => '𐓃',
77738 '𐓬' => '𐓄',
77739 '𐓭' => '𐓅',
77740 '𐓮' => '𐓆',
77741 '𐓯' => '𐓇',
77742 '𐓰' => '𐓈',
77743 '𐓱' => '𐓉',
77744 '𐓲' => '𐓊',
77745 '𐓳' => '𐓋',
77746 '𐓴' => '𐓌',
77747 '𐓵' => '𐓍',
77748 '𐓶' => '𐓎',
77749 '𐓷' => '𐓏',
77750 '𐓸' => '𐓐',
77751 '𐓹' => '𐓑',
77752 '𐓺' => '𐓒',
77753 '𐓻' => '𐓓',
77754 '𐳀' => '𐲀',
77755 '𐳁' => '𐲁',
77756 '𐳂' => '𐲂',
77757 '𐳃' => '𐲃',
77758 '𐳄' => '𐲄',
77759 '𐳅' => '𐲅',
77760 '𐳆' => '𐲆',
77761 '𐳇' => '𐲇',
77762 '𐳈' => '𐲈',
77763 '𐳉' => '𐲉',
77764 '𐳊' => '𐲊',
77765 '𐳋' => '𐲋',
77766 '𐳌' => '𐲌',
77767 '𐳍' => '𐲍',
77768 '𐳎' => '𐲎',
77769 '𐳏' => '𐲏',
77770 '𐳐' => '𐲐',
77771 '𐳑' => '𐲑',
77772 '𐳒' => '𐲒',
77773 '𐳓' => '𐲓',
77774 '𐳔' => '𐲔',
77775 '𐳕' => '𐲕',
77776 '𐳖' => '𐲖',
77777 '𐳗' => '𐲗',
77778 '𐳘' => '𐲘',
77779 '𐳙' => '𐲙',
77780 '𐳚' => '𐲚',
77781 '𐳛' => '𐲛',
77782 '𐳜' => '𐲜',
77783 '𐳝' => '𐲝',
77784 '𐳞' => '𐲞',
77785 '𐳟' => '𐲟',
77786 '𐳠' => '𐲠',
77787 '𐳡' => '𐲡',
77788 '𐳢' => '𐲢',
77789 '𐳣' => '𐲣',
77790 '𐳤' => '𐲤',
77791 '𐳥' => '𐲥',
77792 '𐳦' => '𐲦',
77793 '𐳧' => '𐲧',
77794 '𐳨' => '𐲨',
77795 '𐳩' => '𐲩',
77796 '𐳪' => '𐲪',
77797 '𐳫' => '𐲫',
77798 '𐳬' => '𐲬',
77799 '𐳭' => '𐲭',
77800 '𐳮' => '𐲮',
77801 '𐳯' => '𐲯',
77802 '𐳰' => '𐲰',
77803 '𐳱' => '𐲱',
77804 '𐳲' => '𐲲',
77805 '𑣀' => '𑢠',
77806 '𑣁' => '𑢡',
77807 '𑣂' => '𑢢',
77808 '𑣃' => '𑢣',
77809 '𑣄' => '𑢤',
77810 '𑣅' => '𑢥',
77811 '𑣆' => '𑢦',
77812 '𑣇' => '𑢧',
77813 '𑣈' => '𑢨',
77814 '𑣉' => '𑢩',
77815 '𑣊' => '𑢪',
77816 '𑣋' => '𑢫',
77817 '𑣌' => '𑢬',
77818 '𑣍' => '𑢭',
77819 '𑣎' => '𑢮',
77820 '𑣏' => '𑢯',
77821 '𑣐' => '𑢰',
77822 '𑣑' => '𑢱',
77823 '𑣒' => '𑢲',
77824 '𑣓' => '𑢳',
77825 '𑣔' => '𑢴',
77826 '𑣕' => '𑢵',
77827 '𑣖' => '𑢶',
77828 '𑣗' => '𑢷',
77829 '𑣘' => '𑢸',
77830 '𑣙' => '𑢹',
77831 '𑣚' => '𑢺',
77832 '𑣛' => '𑢻',
77833 '𑣜' => '𑢼',
77834 '𑣝' => '𑢽',
77835 '𑣞' => '𑢾',
77836 '𑣟' => '𑢿',
77837 '𖹠' => '𖹀',
77838 '𖹡' => '𖹁',
77839 '𖹢' => '𖹂',
77840 '𖹣' => '𖹃',
77841 '𖹤' => '𖹄',
77842 '𖹥' => '𖹅',
77843 '𖹦' => '𖹆',
77844 '𖹧' => '𖹇',
77845 '𖹨' => '𖹈',
77846 '𖹩' => '𖹉',
77847 '𖹪' => '𖹊',
77848 '𖹫' => '𖹋',
77849 '𖹬' => '𖹌',
77850 '𖹭' => '𖹍',
77851 '𖹮' => '𖹎',
77852 '𖹯' => '𖹏',
77853 '𖹰' => '𖹐',
77854 '𖹱' => '𖹑',
77855 '𖹲' => '𖹒',
77856 '𖹳' => '𖹓',
77857 '𖹴' => '𖹔',
77858 '𖹵' => '𖹕',
77859 '𖹶' => '𖹖',
77860 '𖹷' => '𖹗',
77861 '𖹸' => '𖹘',
77862 '𖹹' => '𖹙',
77863 '𖹺' => '𖹚',
77864 '𖹻' => '𖹛',
77865 '𖹼' => '𖹜',
77866 '𖹽' => '𖹝',
77867 '𖹾' => '𖹞',
77868 '𖹿' => '𖹟',
77869 '𞤢' => '𞤀',
77870 '𞤣' => '𞤁',
77871 '𞤤' => '𞤂',
77872 '𞤥' => '𞤃',
77873 '𞤦' => '𞤄',
77874 '𞤧' => '𞤅',
77875 '𞤨' => '𞤆',
77876 '𞤩' => '𞤇',
77877 '𞤪' => '𞤈',
77878 '𞤫' => '𞤉',
77879 '𞤬' => '𞤊',
77880 '𞤭' => '𞤋',
77881 '𞤮' => '𞤌',
77882 '𞤯' => '𞤍',
77883 '𞤰' => '𞤎',
77884 '𞤱' => '𞤏',
77885 '𞤲' => '𞤐',
77886 '𞤳' => '𞤑',
77887 '𞤴' => '𞤒',
77888 '𞤵' => '𞤓',
77889 '𞤶' => '𞤔',
77890 '𞤷' => '𞤕',
77891 '𞤸' => '𞤖',
77892 '𞤹' => '𞤗',
77893 '𞤺' => '𞤘',
77894 '𞤻' => '𞤙',
77895 '𞤼' => '𞤚',
77896 '𞤽' => '𞤛',
77897 '𞤾' => '𞤜',
77898 '𞤿' => '𞤝',
77899 '𞥀' => '𞤞',
77900 '𞥁' => '𞤟',
77901 '𞥂' => '𞤠',
77902 '𞥃' => '𞤡',
77903 );
77904 <?php
77905
77906
77907
77908
77909
77910
77911
77912
77913
77914
77915 use Symfony\Polyfill\Mbstring as p;
77916
77917 if (!function_exists('mb_convert_encoding')) {
77918 function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); }
77919 }
77920 if (!function_exists('mb_decode_mimeheader')) {
77921 function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); }
77922 }
77923 if (!function_exists('mb_encode_mimeheader')) {
77924 function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); }
77925 }
77926 if (!function_exists('mb_decode_numericentity')) {
77927 function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); }
77928 }
77929 if (!function_exists('mb_encode_numericentity')) {
77930 function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); }
77931 }
77932 if (!function_exists('mb_convert_case')) {
77933 function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); }
77934 }
77935 if (!function_exists('mb_internal_encoding')) {
77936 function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); }
77937 }
77938 if (!function_exists('mb_language')) {
77939 function mb_language($language = null) { return p\Mbstring::mb_language($language); }
77940 }
77941 if (!function_exists('mb_list_encodings')) {
77942 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
77943 }
77944 if (!function_exists('mb_encoding_aliases')) {
77945 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
77946 }
77947 if (!function_exists('mb_check_encoding')) {
77948 function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); }
77949 }
77950 if (!function_exists('mb_detect_encoding')) {
77951 function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); }
77952 }
77953 if (!function_exists('mb_detect_order')) {
77954 function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); }
77955 }
77956 if (!function_exists('mb_parse_str')) {
77957 function mb_parse_str($string, &$result = array()) { parse_str($string, $result); }
77958 }
77959 if (!function_exists('mb_strlen')) {
77960 function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); }
77961 }
77962 if (!function_exists('mb_strpos')) {
77963 function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); }
77964 }
77965 if (!function_exists('mb_strtolower')) {
77966 function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); }
77967 }
77968 if (!function_exists('mb_strtoupper')) {
77969 function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); }
77970 }
77971 if (!function_exists('mb_substitute_character')) {
77972 function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); }
77973 }
77974 if (!function_exists('mb_substr')) {
77975 function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); }
77976 }
77977 if (!function_exists('mb_stripos')) {
77978 function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); }
77979 }
77980 if (!function_exists('mb_stristr')) {
77981 function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); }
77982 }
77983 if (!function_exists('mb_strrchr')) {
77984 function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); }
77985 }
77986 if (!function_exists('mb_strrichr')) {
77987 function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); }
77988 }
77989 if (!function_exists('mb_strripos')) {
77990 function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); }
77991 }
77992 if (!function_exists('mb_strrpos')) {
77993 function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); }
77994 }
77995 if (!function_exists('mb_strstr')) {
77996 function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); }
77997 }
77998 if (!function_exists('mb_get_info')) {
77999 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
78000 }
78001 if (!function_exists('mb_http_output')) {
78002 function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); }
78003 }
78004 if (!function_exists('mb_strwidth')) {
78005 function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); }
78006 }
78007 if (!function_exists('mb_substr_count')) {
78008 function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); }
78009 }
78010 if (!function_exists('mb_output_handler')) {
78011 function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); }
78012 }
78013 if (!function_exists('mb_http_input')) {
78014 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
78015 }
78016
78017 if (PHP_VERSION_ID >= 80000) {
78018 require_once __DIR__.'/Resources/mb_convert_variables.php8';
78019 } elseif (!function_exists('mb_convert_variables')) {
78020 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); }
78021 }
78022
78023 if (!function_exists('mb_ord')) {
78024 function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); }
78025 }
78026 if (!function_exists('mb_chr')) {
78027 function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); }
78028 }
78029 if (!function_exists('mb_scrub')) {
78030 function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); }
78031 }
78032 if (!function_exists('mb_str_split')) {
78033 function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); }
78034 }
78035
78036 if (extension_loaded('mbstring')) {
78037 return;
78038 }
78039
78040 if (!defined('MB_CASE_UPPER')) {
78041 define('MB_CASE_UPPER', 0);
78042 }
78043 if (!defined('MB_CASE_LOWER')) {
78044 define('MB_CASE_LOWER', 1);
78045 }
78046 if (!defined('MB_CASE_TITLE')) {
78047 define('MB_CASE_TITLE', 2);
78048 }
78049 <?php
78050
78051
78052
78053
78054
78055
78056
78057
78058
78059
78060 namespace Symfony\Component\Process\Exception;
78061
78062
78063
78064
78065
78066
78067 interface ExceptionInterface
78068 {
78069 }
78070 <?php
78071
78072
78073
78074
78075
78076
78077
78078
78079
78080
78081 namespace Symfony\Component\Process\Exception;
78082
78083
78084
78085
78086
78087
78088 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
78089 {
78090 }
78091 <?php
78092
78093
78094
78095
78096
78097
78098
78099
78100
78101
78102 namespace Symfony\Component\Process\Exception;
78103
78104
78105
78106
78107
78108
78109 class LogicException extends \LogicException implements ExceptionInterface
78110 {
78111 }
78112 <?php
78113
78114
78115
78116
78117
78118
78119
78120
78121
78122
78123 namespace Symfony\Component\Process\Exception;
78124
78125 use Symfony\Component\Process\Process;
78126
78127
78128
78129
78130
78131
78132 class ProcessFailedException extends RuntimeException
78133 {
78134 private $process;
78135
78136 public function __construct(Process $process)
78137 {
78138 if ($process->isSuccessful()) {
78139 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
78140 }
78141
78142 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
78143 $process->getCommandLine(),
78144 $process->getExitCode(),
78145 $process->getExitCodeText(),
78146 $process->getWorkingDirectory()
78147 );
78148
78149 if (!$process->isOutputDisabled()) {
78150 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
78151 $process->getOutput(),
78152 $process->getErrorOutput()
78153 );
78154 }
78155
78156 parent::__construct($error);
78157
78158 $this->process = $process;
78159 }
78160
78161 public function getProcess()
78162 {
78163 return $this->process;
78164 }
78165 }
78166 <?php
78167
78168
78169
78170
78171
78172
78173
78174
78175
78176
78177 namespace Symfony\Component\Process\Exception;
78178
78179 use Symfony\Component\Process\Process;
78180
78181
78182
78183
78184
78185
78186 class ProcessTimedOutException extends RuntimeException
78187 {
78188 const TYPE_GENERAL = 1;
78189 const TYPE_IDLE = 2;
78190
78191 private $process;
78192 private $timeoutType;
78193
78194 public function __construct(Process $process, $timeoutType)
78195 {
78196 $this->process = $process;
78197 $this->timeoutType = $timeoutType;
78198
78199 parent::__construct(sprintf(
78200 'The process "%s" exceeded the timeout of %s seconds.',
78201 $process->getCommandLine(),
78202 $this->getExceededTimeout()
78203 ));
78204 }
78205
78206 public function getProcess()
78207 {
78208 return $this->process;
78209 }
78210
78211 public function isGeneralTimeout()
78212 {
78213 return self::TYPE_GENERAL === $this->timeoutType;
78214 }
78215
78216 public function isIdleTimeout()
78217 {
78218 return self::TYPE_IDLE === $this->timeoutType;
78219 }
78220
78221 public function getExceededTimeout()
78222 {
78223 switch ($this->timeoutType) {
78224 case self::TYPE_GENERAL:
78225 return $this->process->getTimeout();
78226
78227 case self::TYPE_IDLE:
78228 return $this->process->getIdleTimeout();
78229
78230 default:
78231 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
78232 }
78233 }
78234 }
78235 <?php
78236
78237
78238
78239
78240
78241
78242
78243
78244
78245
78246 namespace Symfony\Component\Process\Exception;
78247
78248
78249
78250
78251
78252
78253 class RuntimeException extends \RuntimeException implements ExceptionInterface
78254 {
78255 }
78256 <?php
78257
78258
78259
78260
78261
78262
78263
78264
78265
78266
78267 namespace Symfony\Component\Process;
78268
78269
78270
78271
78272
78273
78274
78275 class ExecutableFinder
78276 {
78277 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
78278
78279
78280
78281
78282 public function setSuffixes(array $suffixes)
78283 {
78284 $this->suffixes = $suffixes;
78285 }
78286
78287
78288
78289
78290
78291
78292 public function addSuffix($suffix)
78293 {
78294 $this->suffixes[] = $suffix;
78295 }
78296
78297
78298
78299
78300
78301
78302
78303
78304
78305
78306 public function find($name, $default = null, array $extraDirs = array())
78307 {
78308 if (ini_get('open_basedir')) {
78309 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
78310 $dirs = array();
78311 foreach ($searchPath as $path) {
78312
78313 if (@is_dir($path)) {
78314 $dirs[] = $path;
78315 } else {
78316 if (basename($path) == $name && @is_executable($path)) {
78317 return $path;
78318 }
78319 }
78320 }
78321 } else {
78322 $dirs = array_merge(
78323 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
78324 $extraDirs
78325 );
78326 }
78327
78328 $suffixes = array('');
78329 if ('\\' === \DIRECTORY_SEPARATOR) {
78330 $pathExt = getenv('PATHEXT');
78331 $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
78332 }
78333 foreach ($suffixes as $suffix) {
78334 foreach ($dirs as $dir) {
78335 if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
78336 return $file;
78337 }
78338 }
78339 }
78340
78341 return $default;
78342 }
78343 }
78344 Copyright (c) 2004-2018 Fabien Potencier
78345
78346 Permission is hereby granted, free of charge, to any person obtaining a copy
78347 of this software and associated documentation files (the "Software"), to deal
78348 in the Software without restriction, including without limitation the rights
78349 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
78350 copies of the Software, and to permit persons to whom the Software is furnished
78351 to do so, subject to the following conditions:
78352
78353 The above copyright notice and this permission notice shall be included in all
78354 copies or substantial portions of the Software.
78355
78356 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
78357 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
78358 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
78359 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
78360 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
78361 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
78362 THE SOFTWARE.
78363 <?php
78364
78365
78366
78367
78368
78369
78370
78371
78372
78373
78374 namespace Symfony\Component\Process;
78375
78376
78377
78378
78379
78380
78381
78382 class PhpExecutableFinder
78383 {
78384 private $executableFinder;
78385
78386 public function __construct()
78387 {
78388 $this->executableFinder = new ExecutableFinder();
78389 }
78390
78391
78392
78393
78394
78395
78396
78397
78398 public function find($includeArgs = true)
78399 {
78400 $args = $this->findArguments();
78401 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
78402
78403
78404 if (\defined('HHVM_VERSION')) {
78405 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
78406 }
78407
78408
78409 if (\defined('PHP_BINARY') && PHP_BINARY && \in_array(\PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) {
78410 return PHP_BINARY.$args;
78411 }
78412
78413 if ($php = getenv('PHP_PATH')) {
78414 if (!@is_executable($php)) {
78415 return false;
78416 }
78417
78418 return $php;
78419 }
78420
78421 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
78422 if (@is_executable($php)) {
78423 return $php;
78424 }
78425 }
78426
78427 if (@is_executable($php = PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
78428 return $php;
78429 }
78430
78431 $dirs = array(PHP_BINDIR);
78432 if ('\\' === \DIRECTORY_SEPARATOR) {
78433 $dirs[] = 'C:\xampp\php\\';
78434 }
78435
78436 return $this->executableFinder->find('php', false, $dirs);
78437 }
78438
78439
78440
78441
78442
78443
78444 public function findArguments()
78445 {
78446 $arguments = array();
78447
78448 if (\defined('HHVM_VERSION')) {
78449 $arguments[] = '--php';
78450 } elseif ('phpdbg' === \PHP_SAPI) {
78451 $arguments[] = '-qrr';
78452 }
78453
78454 return $arguments;
78455 }
78456 }
78457 <?php
78458
78459
78460
78461
78462
78463
78464
78465
78466
78467
78468 namespace Symfony\Component\Process;
78469
78470 use Symfony\Component\Process\Exception\RuntimeException;
78471
78472
78473
78474
78475
78476
78477
78478
78479
78480
78481 class PhpProcess extends Process
78482 {
78483
78484
78485
78486
78487
78488
78489
78490 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
78491 {
78492 $executableFinder = new PhpExecutableFinder();
78493 if (false === $php = $executableFinder->find()) {
78494 $php = null;
78495 }
78496 if ('phpdbg' === \PHP_SAPI) {
78497 $file = tempnam(sys_get_temp_dir(), 'dbg');
78498 file_put_contents($file, $script);
78499 register_shutdown_function('unlink', $file);
78500 $php .= ' '.ProcessUtils::escapeArgument($file);
78501 $script = null;
78502 }
78503 if ('\\' !== \DIRECTORY_SEPARATOR && null !== $php) {
78504
78505
78506
78507 $php = 'exec '.$php;
78508 }
78509
78510 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
78511 }
78512
78513
78514
78515
78516 public function setPhpBinary($php)
78517 {
78518 $this->setCommandLine($php);
78519 }
78520
78521
78522
78523
78524 public function start($callback = null)
78525 {
78526 if (null === $this->getCommandLine()) {
78527 throw new RuntimeException('Unable to find the PHP executable.');
78528 }
78529
78530 parent::start($callback);
78531 }
78532 }
78533 <?php
78534
78535
78536
78537
78538
78539
78540
78541
78542
78543
78544 namespace Symfony\Component\Process\Pipes;
78545
78546
78547
78548
78549
78550
78551 abstract class AbstractPipes implements PipesInterface
78552 {
78553 public $pipes = array();
78554
78555 private $inputBuffer = '';
78556 private $input;
78557 private $blocked = true;
78558 private $lastError;
78559
78560
78561
78562
78563 public function __construct($input)
78564 {
78565 if (\is_resource($input)) {
78566 $this->input = $input;
78567 } elseif (\is_string($input)) {
78568 $this->inputBuffer = $input;
78569 } else {
78570 $this->inputBuffer = (string) $input;
78571 }
78572 }
78573
78574
78575
78576
78577 public function close()
78578 {
78579 foreach ($this->pipes as $pipe) {
78580 fclose($pipe);
78581 }
78582 $this->pipes = array();
78583 }
78584
78585
78586
78587
78588
78589
78590 protected function hasSystemCallBeenInterrupted()
78591 {
78592 $lastError = $this->lastError;
78593 $this->lastError = null;
78594
78595
78596 return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
78597 }
78598
78599
78600
78601
78602 protected function unblock()
78603 {
78604 if (!$this->blocked) {
78605 return;
78606 }
78607
78608 foreach ($this->pipes as $pipe) {
78609 stream_set_blocking($pipe, 0);
78610 }
78611 if (null !== $this->input) {
78612 stream_set_blocking($this->input, 0);
78613 }
78614
78615 $this->blocked = false;
78616 }
78617
78618
78619
78620
78621 protected function write()
78622 {
78623 if (!isset($this->pipes[0])) {
78624 return;
78625 }
78626 $input = $this->input;
78627 $r = $e = array();
78628 $w = array($this->pipes[0]);
78629
78630
78631 if (false === @stream_select($r, $w, $e, 0, 0)) {
78632 return;
78633 }
78634
78635 foreach ($w as $stdin) {
78636 if (isset($this->inputBuffer[0])) {
78637 $written = fwrite($stdin, $this->inputBuffer);
78638 $this->inputBuffer = substr($this->inputBuffer, $written);
78639 if (isset($this->inputBuffer[0])) {
78640 return array($this->pipes[0]);
78641 }
78642 }
78643
78644 if ($input) {
78645 for (;;) {
78646 $data = fread($input, self::CHUNK_SIZE);
78647 if (!isset($data[0])) {
78648 break;
78649 }
78650 $written = fwrite($stdin, $data);
78651 $data = substr($data, $written);
78652 if (isset($data[0])) {
78653 $this->inputBuffer = $data;
78654
78655 return array($this->pipes[0]);
78656 }
78657 }
78658 if (feof($input)) {
78659
78660
78661 $this->input = null;
78662 }
78663 }
78664 }
78665
78666
78667 if (null === $this->input && !isset($this->inputBuffer[0])) {
78668 fclose($this->pipes[0]);
78669 unset($this->pipes[0]);
78670 } elseif (!$w) {
78671 return array($this->pipes[0]);
78672 }
78673 }
78674
78675
78676
78677
78678 public function handleError($type, $msg)
78679 {
78680 $this->lastError = $msg;
78681 }
78682 }
78683 <?php
78684
78685
78686
78687
78688
78689
78690
78691
78692
78693
78694 namespace Symfony\Component\Process\Pipes;
78695
78696
78697
78698
78699
78700
78701
78702
78703 interface PipesInterface
78704 {
78705 const CHUNK_SIZE = 16384;
78706
78707
78708
78709
78710
78711
78712 public function getDescriptors();
78713
78714
78715
78716
78717
78718
78719 public function getFiles();
78720
78721
78722
78723
78724
78725
78726
78727
78728
78729 public function readAndWrite($blocking, $close = false);
78730
78731
78732
78733
78734
78735
78736 public function areOpen();
78737
78738
78739
78740
78741 public function close();
78742 }
78743 <?php
78744
78745
78746
78747
78748
78749
78750
78751
78752
78753
78754 namespace Symfony\Component\Process\Pipes;
78755
78756 use Symfony\Component\Process\Process;
78757
78758
78759
78760
78761
78762
78763
78764
78765 class UnixPipes extends AbstractPipes
78766 {
78767 private $ttyMode;
78768 private $ptyMode;
78769 private $disableOutput;
78770
78771 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
78772 {
78773 $this->ttyMode = (bool) $ttyMode;
78774 $this->ptyMode = (bool) $ptyMode;
78775 $this->disableOutput = (bool) $disableOutput;
78776
78777 parent::__construct($input);
78778 }
78779
78780 public function __destruct()
78781 {
78782 $this->close();
78783 }
78784
78785
78786
78787
78788 public function getDescriptors()
78789 {
78790 if ($this->disableOutput) {
78791 $nullstream = fopen('/dev/null', 'c');
78792
78793 return array(
78794 array('pipe', 'r'),
78795 $nullstream,
78796 $nullstream,
78797 );
78798 }
78799
78800 if ($this->ttyMode) {
78801 return array(
78802 array('file', '/dev/tty', 'r'),
78803 array('file', '/dev/tty', 'w'),
78804 array('file', '/dev/tty', 'w'),
78805 );
78806 }
78807
78808 if ($this->ptyMode && Process::isPtySupported()) {
78809 return array(
78810 array('pty'),
78811 array('pty'),
78812 array('pty'),
78813 );
78814 }
78815
78816 return array(
78817 array('pipe', 'r'),
78818 array('pipe', 'w'), 
78819 array('pipe', 'w'), 
78820 );
78821 }
78822
78823
78824
78825
78826 public function getFiles()
78827 {
78828 return array();
78829 }
78830
78831
78832
78833
78834 public function readAndWrite($blocking, $close = false)
78835 {
78836 $this->unblock();
78837 $w = $this->write();
78838
78839 $read = $e = array();
78840 $r = $this->pipes;
78841 unset($r[0]);
78842
78843
78844 set_error_handler(array($this, 'handleError'));
78845 if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
78846 restore_error_handler();
78847
78848
78849 if (!$this->hasSystemCallBeenInterrupted()) {
78850 $this->pipes = array();
78851 }
78852
78853 return $read;
78854 }
78855 restore_error_handler();
78856
78857 foreach ($r as $pipe) {
78858
78859
78860 $read[$type = array_search($pipe, $this->pipes, true)] = '';
78861
78862 do {
78863 $data = fread($pipe, self::CHUNK_SIZE);
78864 $read[$type] .= $data;
78865 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
78866
78867 if (!isset($read[$type][0])) {
78868 unset($read[$type]);
78869 }
78870
78871 if ($close && feof($pipe)) {
78872 fclose($pipe);
78873 unset($this->pipes[$type]);
78874 }
78875 }
78876
78877 return $read;
78878 }
78879
78880
78881
78882
78883 public function areOpen()
78884 {
78885 return (bool) $this->pipes;
78886 }
78887
78888
78889
78890
78891
78892
78893
78894
78895
78896 public static function create(Process $process, $input)
78897 {
78898 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
78899 }
78900 }
78901 <?php
78902
78903
78904
78905
78906
78907
78908
78909
78910
78911
78912 namespace Symfony\Component\Process\Pipes;
78913
78914 use Symfony\Component\Process\Exception\RuntimeException;
78915 use Symfony\Component\Process\Process;
78916
78917
78918
78919
78920
78921
78922
78923
78924
78925
78926
78927 class WindowsPipes extends AbstractPipes
78928 {
78929 private $files = array();
78930 private $fileHandles = array();
78931 private $lockHandles = array();
78932 private $readBytes = array(
78933 Process::STDOUT => 0,
78934 Process::STDERR => 0,
78935 );
78936 private $disableOutput;
78937
78938 public function __construct($disableOutput, $input)
78939 {
78940 $this->disableOutput = (bool) $disableOutput;
78941
78942 if (!$this->disableOutput) {
78943
78944
78945
78946
78947 $pipes = array(
78948 Process::STDOUT => Process::OUT,
78949 Process::STDERR => Process::ERR,
78950 );
78951 $tmpDir = sys_get_temp_dir();
78952 $lastError = 'unknown reason';
78953 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
78954 for ($i = 0;; ++$i) {
78955 foreach ($pipes as $pipe => $name) {
78956 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
78957
78958 if (!$h = fopen($file.'.lock', 'w')) {
78959 restore_error_handler();
78960 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $lastError));
78961 }
78962 if (!flock($h, LOCK_EX | LOCK_NB)) {
78963 continue 2;
78964 }
78965 if (isset($this->lockHandles[$pipe])) {
78966 flock($this->lockHandles[$pipe], LOCK_UN);
78967 fclose($this->lockHandles[$pipe]);
78968 }
78969 $this->lockHandles[$pipe] = $h;
78970
78971 if (!fclose(fopen($file, 'w')) || !$h = fopen($file, 'r')) {
78972 flock($this->lockHandles[$pipe], LOCK_UN);
78973 fclose($this->lockHandles[$pipe]);
78974 unset($this->lockHandles[$pipe]);
78975 continue 2;
78976 }
78977 $this->fileHandles[$pipe] = $h;
78978 $this->files[$pipe] = $file;
78979 }
78980 break;
78981 }
78982 restore_error_handler();
78983 }
78984
78985 parent::__construct($input);
78986 }
78987
78988 public function __destruct()
78989 {
78990 $this->close();
78991 }
78992
78993
78994
78995
78996 public function getDescriptors()
78997 {
78998 if ($this->disableOutput) {
78999 $nullstream = fopen('NUL', 'c');
79000
79001 return array(
79002 array('pipe', 'r'),
79003 $nullstream,
79004 $nullstream,
79005 );
79006 }
79007
79008
79009
79010
79011 return array(
79012 array('pipe', 'r'),
79013 array('file', 'NUL', 'w'),
79014 array('file', 'NUL', 'w'),
79015 );
79016 }
79017
79018
79019
79020
79021 public function getFiles()
79022 {
79023 return $this->files;
79024 }
79025
79026
79027
79028
79029 public function readAndWrite($blocking, $close = false)
79030 {
79031 $this->unblock();
79032 $w = $this->write();
79033 $read = $r = $e = array();
79034
79035 if ($blocking) {
79036 if ($w) {
79037 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
79038 } elseif ($this->fileHandles) {
79039 usleep(Process::TIMEOUT_PRECISION * 1E6);
79040 }
79041 }
79042 foreach ($this->fileHandles as $type => $fileHandle) {
79043 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
79044
79045 if (isset($data[0])) {
79046 $this->readBytes[$type] += \strlen($data);
79047 $read[$type] = $data;
79048 }
79049 if ($close) {
79050 ftruncate($fileHandle, 0);
79051 fclose($fileHandle);
79052 flock($this->lockHandles[$type], LOCK_UN);
79053 fclose($this->lockHandles[$type]);
79054 unset($this->fileHandles[$type], $this->lockHandles[$type]);
79055 }
79056 }
79057
79058 return $read;
79059 }
79060
79061
79062
79063
79064 public function areOpen()
79065 {
79066 return $this->pipes && $this->fileHandles;
79067 }
79068
79069
79070
79071
79072 public function close()
79073 {
79074 parent::close();
79075 foreach ($this->fileHandles as $type => $handle) {
79076 ftruncate($handle, 0);
79077 fclose($handle);
79078 flock($this->lockHandles[$type], LOCK_UN);
79079 fclose($this->lockHandles[$type]);
79080 }
79081 $this->fileHandles = $this->lockHandles = array();
79082 }
79083
79084
79085
79086
79087
79088
79089
79090
79091
79092 public static function create(Process $process, $input)
79093 {
79094 return new static($process->isOutputDisabled(), $input);
79095 }
79096 }
79097 <?php
79098
79099
79100
79101
79102
79103
79104
79105
79106
79107
79108 namespace Symfony\Component\Process;
79109
79110 use Symfony\Component\Process\Exception\InvalidArgumentException;
79111 use Symfony\Component\Process\Exception\LogicException;
79112 use Symfony\Component\Process\Exception\ProcessFailedException;
79113 use Symfony\Component\Process\Exception\ProcessTimedOutException;
79114 use Symfony\Component\Process\Exception\RuntimeException;
79115 use Symfony\Component\Process\Pipes\PipesInterface;
79116 use Symfony\Component\Process\Pipes\UnixPipes;
79117 use Symfony\Component\Process\Pipes\WindowsPipes;
79118
79119
79120
79121
79122
79123
79124
79125
79126 class Process
79127 {
79128 const ERR = 'err';
79129 const OUT = 'out';
79130
79131 const STATUS_READY = 'ready';
79132 const STATUS_STARTED = 'started';
79133 const STATUS_TERMINATED = 'terminated';
79134
79135 const STDIN = 0;
79136 const STDOUT = 1;
79137 const STDERR = 2;
79138
79139
79140 const TIMEOUT_PRECISION = 0.2;
79141
79142 private $callback;
79143 private $commandline;
79144 private $cwd;
79145 private $env;
79146 private $input;
79147 private $starttime;
79148 private $lastOutputTime;
79149 private $timeout;
79150 private $idleTimeout;
79151 private $options;
79152 private $exitcode;
79153 private $fallbackStatus = array();
79154 private $processInformation;
79155 private $outputDisabled = false;
79156 private $stdout;
79157 private $stderr;
79158 private $enhanceWindowsCompatibility = true;
79159 private $enhanceSigchildCompatibility;
79160 private $process;
79161 private $status = self::STATUS_READY;
79162 private $incrementalOutputOffset = 0;
79163 private $incrementalErrorOutputOffset = 0;
79164 private $tty;
79165 private $pty;
79166
79167 private $useFileHandles = false;
79168
79169 private $processPipes;
79170
79171 private $latestSignal;
79172
79173 private static $sigchild;
79174
79175
79176
79177
79178
79179
79180 public static $exitCodes = array(
79181 0 => 'OK',
79182 1 => 'General error',
79183 2 => 'Misuse of shell builtins',
79184
79185 126 => 'Invoked command cannot execute',
79186 127 => 'Command not found',
79187 128 => 'Invalid exit argument',
79188
79189
79190 129 => 'Hangup',
79191 130 => 'Interrupt',
79192 131 => 'Quit and dump core',
79193 132 => 'Illegal instruction',
79194 133 => 'Trace/breakpoint trap',
79195 134 => 'Process aborted',
79196 135 => 'Bus error: "access to undefined portion of memory object"',
79197 136 => 'Floating point exception: "erroneous arithmetic operation"',
79198 137 => 'Kill (terminate immediately)',
79199 138 => 'User-defined 1',
79200 139 => 'Segmentation violation',
79201 140 => 'User-defined 2',
79202 141 => 'Write to pipe with no one reading',
79203 142 => 'Signal raised by alarm',
79204 143 => 'Termination (request to terminate)',
79205
79206 145 => 'Child process terminated, stopped (or continued*)',
79207 146 => 'Continue if stopped',
79208 147 => 'Stop executing temporarily',
79209 148 => 'Terminal stop signal',
79210 149 => 'Background process attempting to read from tty ("in")',
79211 150 => 'Background process attempting to write to tty ("out")',
79212 151 => 'Urgent data available on socket',
79213 152 => 'CPU time limit exceeded',
79214 153 => 'File size limit exceeded',
79215 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
79216 155 => 'Profiling timer expired',
79217
79218 157 => 'Pollable event',
79219
79220 159 => 'Bad syscall',
79221 );
79222
79223
79224
79225
79226
79227
79228
79229
79230
79231
79232
79233 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
79234 {
79235 if (!\function_exists('proc_open')) {
79236 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
79237 }
79238
79239 $this->commandline = $commandline;
79240 $this->cwd = $cwd;
79241
79242
79243
79244
79245
79246 if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
79247 $this->cwd = getcwd();
79248 }
79249 if (null !== $env) {
79250 $this->setEnv($env);
79251 }
79252
79253 $this->setInput($input);
79254 $this->setTimeout($timeout);
79255 $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR;
79256 $this->pty = false;
79257 $this->enhanceSigchildCompatibility = '\\' !== \DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
79258 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
79259 }
79260
79261 public function __destruct()
79262 {
79263 $this->stop(0);
79264 }
79265
79266 public function __clone()
79267 {
79268 $this->resetProcessData();
79269 }
79270
79271
79272
79273
79274
79275
79276
79277
79278
79279
79280
79281
79282
79283
79284
79285
79286
79287
79288
79289
79290 public function run($callback = null)
79291 {
79292 $this->start($callback);
79293
79294 return $this->wait();
79295 }
79296
79297
79298
79299
79300
79301
79302
79303
79304
79305
79306
79307
79308
79309
79310 public function mustRun($callback = null)
79311 {
79312 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
79313 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
79314 }
79315
79316 if (0 !== $this->run($callback)) {
79317 throw new ProcessFailedException($this);
79318 }
79319
79320 return $this;
79321 }
79322
79323
79324
79325
79326
79327
79328
79329
79330
79331
79332
79333
79334
79335
79336
79337
79338
79339
79340
79341
79342 public function start($callback = null)
79343 {
79344 if ($this->isRunning()) {
79345 throw new RuntimeException('Process is already running');
79346 }
79347 if ($this->outputDisabled && null !== $callback) {
79348 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
79349 }
79350
79351 $this->resetProcessData();
79352 $this->starttime = $this->lastOutputTime = microtime(true);
79353 $this->callback = $this->buildCallback($callback);
79354 $descriptors = $this->getDescriptors();
79355
79356 $commandline = $this->commandline;
79357
79358 if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
79359 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
79360 foreach ($this->processPipes->getFiles() as $offset => $filename) {
79361 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
79362 }
79363 $commandline .= '"';
79364
79365 if (!isset($this->options['bypass_shell'])) {
79366 $this->options['bypass_shell'] = true;
79367 }
79368 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
79369
79370 $descriptors[3] = array('pipe', 'w');
79371
79372
79373 $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
79374 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
79375
79376
79377
79378 $ptsWorkaround = fopen(__FILE__, 'r');
79379 }
79380
79381 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
79382
79383 if (!\is_resource($this->process)) {
79384 throw new RuntimeException('Unable to launch a new process.');
79385 }
79386 $this->status = self::STATUS_STARTED;
79387
79388 if (isset($descriptors[3])) {
79389 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
79390 }
79391
79392 if ($this->tty) {
79393 return;
79394 }
79395
79396 $this->updateStatus(false);
79397 $this->checkTimeout();
79398 }
79399
79400
79401
79402
79403
79404
79405
79406
79407
79408
79409
79410
79411
79412
79413
79414
79415 public function restart($callback = null)
79416 {
79417 if ($this->isRunning()) {
79418 throw new RuntimeException('Process is already running');
79419 }
79420
79421 $process = clone $this;
79422 $process->start($callback);
79423
79424 return $process;
79425 }
79426
79427
79428
79429
79430
79431
79432
79433
79434
79435
79436
79437
79438
79439
79440
79441
79442 public function wait($callback = null)
79443 {
79444 $this->requireProcessIsStarted(__FUNCTION__);
79445
79446 $this->updateStatus(false);
79447 if (null !== $callback) {
79448 $this->callback = $this->buildCallback($callback);
79449 }
79450
79451 do {
79452 $this->checkTimeout();
79453 $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
79454 $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
79455 } while ($running);
79456
79457 while ($this->isRunning()) {
79458 usleep(1000);
79459 }
79460
79461 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
79462 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
79463 }
79464
79465 return $this->exitcode;
79466 }
79467
79468
79469
79470
79471
79472
79473 public function getPid()
79474 {
79475 return $this->isRunning() ? $this->processInformation['pid'] : null;
79476 }
79477
79478
79479
79480
79481
79482
79483
79484
79485
79486
79487
79488
79489 public function signal($signal)
79490 {
79491 $this->doSignal($signal, true);
79492
79493 return $this;
79494 }
79495
79496
79497
79498
79499
79500
79501
79502
79503
79504 public function disableOutput()
79505 {
79506 if ($this->isRunning()) {
79507 throw new RuntimeException('Disabling output while the process is running is not possible.');
79508 }
79509 if (null !== $this->idleTimeout) {
79510 throw new LogicException('Output can not be disabled while an idle timeout is set.');
79511 }
79512
79513 $this->outputDisabled = true;
79514
79515 return $this;
79516 }
79517
79518
79519
79520
79521
79522
79523
79524
79525 public function enableOutput()
79526 {
79527 if ($this->isRunning()) {
79528 throw new RuntimeException('Enabling output while the process is running is not possible.');
79529 }
79530
79531 $this->outputDisabled = false;
79532
79533 return $this;
79534 }
79535
79536
79537
79538
79539
79540
79541 public function isOutputDisabled()
79542 {
79543 return $this->outputDisabled;
79544 }
79545
79546
79547
79548
79549
79550
79551
79552
79553
79554 public function getOutput()
79555 {
79556 $this->readPipesForOutput(__FUNCTION__);
79557
79558 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
79559 return '';
79560 }
79561
79562 return $ret;
79563 }
79564
79565
79566
79567
79568
79569
79570
79571
79572
79573
79574
79575
79576 public function getIncrementalOutput()
79577 {
79578 $this->readPipesForOutput(__FUNCTION__);
79579
79580 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
79581 $this->incrementalOutputOffset = ftell($this->stdout);
79582
79583 if (false === $latest) {
79584 return '';
79585 }
79586
79587 return $latest;
79588 }
79589
79590
79591
79592
79593
79594
79595 public function clearOutput()
79596 {
79597 ftruncate($this->stdout, 0);
79598 fseek($this->stdout, 0);
79599 $this->incrementalOutputOffset = 0;
79600
79601 return $this;
79602 }
79603
79604
79605
79606
79607
79608
79609
79610
79611
79612 public function getErrorOutput()
79613 {
79614 $this->readPipesForOutput(__FUNCTION__);
79615
79616 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
79617 return '';
79618 }
79619
79620 return $ret;
79621 }
79622
79623
79624
79625
79626
79627
79628
79629
79630
79631
79632
79633
79634
79635 public function getIncrementalErrorOutput()
79636 {
79637 $this->readPipesForOutput(__FUNCTION__);
79638
79639 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
79640 $this->incrementalErrorOutputOffset = ftell($this->stderr);
79641
79642 if (false === $latest) {
79643 return '';
79644 }
79645
79646 return $latest;
79647 }
79648
79649
79650
79651
79652
79653
79654 public function clearErrorOutput()
79655 {
79656 ftruncate($this->stderr, 0);
79657 fseek($this->stderr, 0);
79658 $this->incrementalErrorOutputOffset = 0;
79659
79660 return $this;
79661 }
79662
79663
79664
79665
79666
79667
79668
79669
79670 public function getExitCode()
79671 {
79672 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
79673 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
79674 }
79675
79676 $this->updateStatus(false);
79677
79678 return $this->exitcode;
79679 }
79680
79681
79682
79683
79684
79685
79686
79687
79688
79689
79690
79691
79692 public function getExitCodeText()
79693 {
79694 if (null === $exitcode = $this->getExitCode()) {
79695 return;
79696 }
79697
79698 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
79699 }
79700
79701
79702
79703
79704
79705
79706 public function isSuccessful()
79707 {
79708 return 0 === $this->getExitCode();
79709 }
79710
79711
79712
79713
79714
79715
79716
79717
79718
79719
79720
79721 public function hasBeenSignaled()
79722 {
79723 $this->requireProcessIsTerminated(__FUNCTION__);
79724
79725 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
79726 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
79727 }
79728
79729 return $this->processInformation['signaled'];
79730 }
79731
79732
79733
79734
79735
79736
79737
79738
79739
79740
79741
79742 public function getTermSignal()
79743 {
79744 $this->requireProcessIsTerminated(__FUNCTION__);
79745
79746 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
79747 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
79748 }
79749
79750 return $this->processInformation['termsig'];
79751 }
79752
79753
79754
79755
79756
79757
79758
79759
79760
79761
79762 public function hasBeenStopped()
79763 {
79764 $this->requireProcessIsTerminated(__FUNCTION__);
79765
79766 return $this->processInformation['stopped'];
79767 }
79768
79769
79770
79771
79772
79773
79774
79775
79776
79777
79778 public function getStopSignal()
79779 {
79780 $this->requireProcessIsTerminated(__FUNCTION__);
79781
79782 return $this->processInformation['stopsig'];
79783 }
79784
79785
79786
79787
79788
79789
79790 public function isRunning()
79791 {
79792 if (self::STATUS_STARTED !== $this->status) {
79793 return false;
79794 }
79795
79796 $this->updateStatus(false);
79797
79798 return $this->processInformation['running'];
79799 }
79800
79801
79802
79803
79804
79805
79806 public function isStarted()
79807 {
79808 return self::STATUS_READY != $this->status;
79809 }
79810
79811
79812
79813
79814
79815
79816 public function isTerminated()
79817 {
79818 $this->updateStatus(false);
79819
79820 return self::STATUS_TERMINATED == $this->status;
79821 }
79822
79823
79824
79825
79826
79827
79828
79829
79830 public function getStatus()
79831 {
79832 $this->updateStatus(false);
79833
79834 return $this->status;
79835 }
79836
79837
79838
79839
79840
79841
79842
79843
79844
79845 public function stop($timeout = 10, $signal = null)
79846 {
79847 $timeoutMicro = microtime(true) + $timeout;
79848 if ($this->isRunning()) {
79849
79850 $this->doSignal(15, false);
79851 do {
79852 usleep(1000);
79853 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
79854
79855 if ($this->isRunning()) {
79856
79857
79858 $this->doSignal($signal ?: 9, false);
79859 }
79860 }
79861
79862 if ($this->isRunning()) {
79863 if (isset($this->fallbackStatus['pid'])) {
79864 unset($this->fallbackStatus['pid']);
79865
79866 return $this->stop(0, $signal);
79867 }
79868 $this->close();
79869 }
79870
79871 return $this->exitcode;
79872 }
79873
79874
79875
79876
79877
79878
79879
79880
79881 public function addOutput($line)
79882 {
79883 $this->lastOutputTime = microtime(true);
79884
79885 fseek($this->stdout, 0, SEEK_END);
79886 fwrite($this->stdout, $line);
79887 fseek($this->stdout, $this->incrementalOutputOffset);
79888 }
79889
79890
79891
79892
79893
79894
79895
79896
79897 public function addErrorOutput($line)
79898 {
79899 $this->lastOutputTime = microtime(true);
79900
79901 fseek($this->stderr, 0, SEEK_END);
79902 fwrite($this->stderr, $line);
79903 fseek($this->stderr, $this->incrementalErrorOutputOffset);
79904 }
79905
79906
79907
79908
79909
79910
79911 public function getCommandLine()
79912 {
79913 return $this->commandline;
79914 }
79915
79916
79917
79918
79919
79920
79921
79922
79923 public function setCommandLine($commandline)
79924 {
79925 $this->commandline = $commandline;
79926
79927 return $this;
79928 }
79929
79930
79931
79932
79933
79934
79935 public function getTimeout()
79936 {
79937 return $this->timeout;
79938 }
79939
79940
79941
79942
79943
79944
79945 public function getIdleTimeout()
79946 {
79947 return $this->idleTimeout;
79948 }
79949
79950
79951
79952
79953
79954
79955
79956
79957
79958
79959
79960
79961 public function setTimeout($timeout)
79962 {
79963 $this->timeout = $this->validateTimeout($timeout);
79964
79965 return $this;
79966 }
79967
79968
79969
79970
79971
79972
79973
79974
79975
79976
79977
79978
79979
79980 public function setIdleTimeout($timeout)
79981 {
79982 if (null !== $timeout && $this->outputDisabled) {
79983 throw new LogicException('Idle timeout can not be set while the output is disabled.');
79984 }
79985
79986 $this->idleTimeout = $this->validateTimeout($timeout);
79987
79988 return $this;
79989 }
79990
79991
79992
79993
79994
79995
79996
79997
79998
79999
80000 public function setTty($tty)
80001 {
80002 if ('\\' === \DIRECTORY_SEPARATOR && $tty) {
80003 throw new RuntimeException('TTY mode is not supported on Windows platform.');
80004 }
80005 if ($tty) {
80006 static $isTtySupported;
80007
80008 if (null === $isTtySupported) {
80009 $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);
80010 }
80011
80012 if (!$isTtySupported) {
80013 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
80014 }
80015 }
80016
80017 $this->tty = (bool) $tty;
80018
80019 return $this;
80020 }
80021
80022
80023
80024
80025
80026
80027 public function isTty()
80028 {
80029 return $this->tty;
80030 }
80031
80032
80033
80034
80035
80036
80037
80038
80039 public function setPty($bool)
80040 {
80041 $this->pty = (bool) $bool;
80042
80043 return $this;
80044 }
80045
80046
80047
80048
80049
80050
80051 public function isPty()
80052 {
80053 return $this->pty;
80054 }
80055
80056
80057
80058
80059
80060
80061 public function getWorkingDirectory()
80062 {
80063 if (null === $this->cwd) {
80064
80065
80066 return getcwd() ?: null;
80067 }
80068
80069 return $this->cwd;
80070 }
80071
80072
80073
80074
80075
80076
80077
80078
80079 public function setWorkingDirectory($cwd)
80080 {
80081 $this->cwd = $cwd;
80082
80083 return $this;
80084 }
80085
80086
80087
80088
80089
80090
80091 public function getEnv()
80092 {
80093 return $this->env;
80094 }
80095
80096
80097
80098
80099
80100
80101
80102
80103
80104
80105
80106
80107
80108
80109 public function setEnv(array $env)
80110 {
80111
80112 $env = array_filter($env, function ($value) {
80113 return !\is_array($value);
80114 });
80115
80116 $this->env = array();
80117 foreach ($env as $key => $value) {
80118 $this->env[$key] = (string) $value;
80119 }
80120
80121 return $this;
80122 }
80123
80124
80125
80126
80127
80128
80129
80130
80131
80132
80133 public function getStdin()
80134 {
80135 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the getInput() method instead.', E_USER_DEPRECATED);
80136
80137 return $this->getInput();
80138 }
80139
80140
80141
80142
80143
80144
80145 public function getInput()
80146 {
80147 return $this->input;
80148 }
80149
80150
80151
80152
80153
80154
80155
80156
80157
80158
80159
80160
80161
80162
80163 public function setStdin($stdin)
80164 {
80165 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the setInput() method instead.', E_USER_DEPRECATED);
80166
80167 return $this->setInput($stdin);
80168 }
80169
80170
80171
80172
80173
80174
80175
80176
80177
80178
80179
80180
80181
80182
80183 public function setInput($input)
80184 {
80185 if ($this->isRunning()) {
80186 throw new LogicException('Input can not be set while the process is running.');
80187 }
80188
80189 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
80190
80191 return $this;
80192 }
80193
80194
80195
80196
80197
80198
80199 public function getOptions()
80200 {
80201 return $this->options;
80202 }
80203
80204
80205
80206
80207
80208
80209
80210
80211 public function setOptions(array $options)
80212 {
80213 $this->options = $options;
80214
80215 return $this;
80216 }
80217
80218
80219
80220
80221
80222
80223
80224
80225 public function getEnhanceWindowsCompatibility()
80226 {
80227 return $this->enhanceWindowsCompatibility;
80228 }
80229
80230
80231
80232
80233
80234
80235
80236
80237 public function setEnhanceWindowsCompatibility($enhance)
80238 {
80239 $this->enhanceWindowsCompatibility = (bool) $enhance;
80240
80241 return $this;
80242 }
80243
80244
80245
80246
80247
80248
80249 public function getEnhanceSigchildCompatibility()
80250 {
80251 return $this->enhanceSigchildCompatibility;
80252 }
80253
80254
80255
80256
80257
80258
80259
80260
80261
80262
80263
80264
80265 public function setEnhanceSigchildCompatibility($enhance)
80266 {
80267 $this->enhanceSigchildCompatibility = (bool) $enhance;
80268
80269 return $this;
80270 }
80271
80272
80273
80274
80275
80276
80277
80278
80279
80280 public function checkTimeout()
80281 {
80282 if (self::STATUS_STARTED !== $this->status) {
80283 return;
80284 }
80285
80286 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
80287 $this->stop(0);
80288
80289 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
80290 }
80291
80292 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
80293 $this->stop(0);
80294
80295 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
80296 }
80297 }
80298
80299
80300
80301
80302
80303
80304 public static function isPtySupported()
80305 {
80306 static $result;
80307
80308 if (null !== $result) {
80309 return $result;
80310 }
80311
80312 if ('\\' === \DIRECTORY_SEPARATOR) {
80313 return $result = false;
80314 }
80315
80316 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
80317 }
80318
80319
80320
80321
80322
80323
80324 private function getDescriptors()
80325 {
80326 if ('\\' === \DIRECTORY_SEPARATOR) {
80327 $this->processPipes = WindowsPipes::create($this, $this->input);
80328 } else {
80329 $this->processPipes = UnixPipes::create($this, $this->input);
80330 }
80331
80332 return $this->processPipes->getDescriptors();
80333 }
80334
80335
80336
80337
80338
80339
80340
80341
80342
80343
80344
80345 protected function buildCallback($callback)
80346 {
80347 $that = $this;
80348 $out = self::OUT;
80349 $callback = function ($type, $data) use ($that, $callback, $out) {
80350 if ($out == $type) {
80351 $that->addOutput($data);
80352 } else {
80353 $that->addErrorOutput($data);
80354 }
80355
80356 if (null !== $callback) {
80357 \call_user_func($callback, $type, $data);
80358 }
80359 };
80360
80361 return $callback;
80362 }
80363
80364
80365
80366
80367
80368
80369 protected function updateStatus($blocking)
80370 {
80371 if (self::STATUS_STARTED !== $this->status) {
80372 return;
80373 }
80374
80375 $this->processInformation = proc_get_status($this->process);
80376 $running = $this->processInformation['running'];
80377
80378 $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);
80379
80380 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
80381 $this->processInformation = $this->fallbackStatus + $this->processInformation;
80382 }
80383
80384 if (!$running) {
80385 $this->close();
80386 }
80387 }
80388
80389
80390
80391
80392
80393
80394 protected function isSigchildEnabled()
80395 {
80396 if (null !== self::$sigchild) {
80397 return self::$sigchild;
80398 }
80399
80400 if (!\function_exists('phpinfo') || \defined('HHVM_VERSION')) {
80401 return self::$sigchild = false;
80402 }
80403
80404 ob_start();
80405 phpinfo(INFO_GENERAL);
80406
80407 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
80408 }
80409
80410
80411
80412
80413
80414
80415
80416
80417 private function readPipesForOutput($caller)
80418 {
80419 if ($this->outputDisabled) {
80420 throw new LogicException('Output has been disabled.');
80421 }
80422
80423 $this->requireProcessIsStarted($caller);
80424
80425 $this->updateStatus(false);
80426 }
80427
80428
80429
80430
80431
80432
80433
80434
80435
80436
80437 private function validateTimeout($timeout)
80438 {
80439 $timeout = (float) $timeout;
80440
80441 if (0.0 === $timeout) {
80442 $timeout = null;
80443 } elseif ($timeout < 0) {
80444 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
80445 }
80446
80447 return $timeout;
80448 }
80449
80450
80451
80452
80453
80454
80455
80456 private function readPipes($blocking, $close)
80457 {
80458 $result = $this->processPipes->readAndWrite($blocking, $close);
80459
80460 $callback = $this->callback;
80461 foreach ($result as $type => $data) {
80462 if (3 !== $type) {
80463 $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
80464 } elseif (!isset($this->fallbackStatus['signaled'])) {
80465 $this->fallbackStatus['exitcode'] = (int) $data;
80466 }
80467 }
80468 }
80469
80470
80471
80472
80473
80474
80475 private function close()
80476 {
80477 $this->processPipes->close();
80478 if (\is_resource($this->process)) {
80479 proc_close($this->process);
80480 }
80481 $this->exitcode = $this->processInformation['exitcode'];
80482 $this->status = self::STATUS_TERMINATED;
80483
80484 if (-1 === $this->exitcode) {
80485 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
80486
80487 $this->exitcode = 128 + $this->processInformation['termsig'];
80488 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
80489 $this->processInformation['signaled'] = true;
80490 $this->processInformation['termsig'] = -1;
80491 }
80492 }
80493
80494
80495
80496
80497 $this->callback = null;
80498
80499 return $this->exitcode;
80500 }
80501
80502
80503
80504
80505 private function resetProcessData()
80506 {
80507 $this->starttime = null;
80508 $this->callback = null;
80509 $this->exitcode = null;
80510 $this->fallbackStatus = array();
80511 $this->processInformation = null;
80512 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
80513 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
80514 $this->process = null;
80515 $this->latestSignal = null;
80516 $this->status = self::STATUS_READY;
80517 $this->incrementalOutputOffset = 0;
80518 $this->incrementalErrorOutputOffset = 0;
80519 }
80520
80521
80522
80523
80524
80525
80526
80527
80528
80529
80530
80531
80532
80533 private function doSignal($signal, $throwException)
80534 {
80535 if (null === $pid = $this->getPid()) {
80536 if ($throwException) {
80537 throw new LogicException('Can not send signal on a non running process.');
80538 }
80539
80540 return false;
80541 }
80542
80543 if ('\\' === \DIRECTORY_SEPARATOR) {
80544 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
80545 if ($exitCode && $this->isRunning()) {
80546 if ($throwException) {
80547 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
80548 }
80549
80550 return false;
80551 }
80552 } else {
80553 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
80554 $ok = @proc_terminate($this->process, $signal);
80555 } elseif (\function_exists('posix_kill')) {
80556 $ok = @posix_kill($pid, $signal);
80557 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
80558 $ok = false === fgets($pipes[2]);
80559 }
80560 if (!$ok) {
80561 if ($throwException) {
80562 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
80563 }
80564
80565 return false;
80566 }
80567 }
80568
80569 $this->latestSignal = (int) $signal;
80570 $this->fallbackStatus['signaled'] = true;
80571 $this->fallbackStatus['exitcode'] = -1;
80572 $this->fallbackStatus['termsig'] = $this->latestSignal;
80573
80574 return true;
80575 }
80576
80577
80578
80579
80580
80581
80582
80583
80584 private function requireProcessIsStarted($functionName)
80585 {
80586 if (!$this->isStarted()) {
80587 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
80588 }
80589 }
80590
80591
80592
80593
80594
80595
80596
80597
80598 private function requireProcessIsTerminated($functionName)
80599 {
80600 if (!$this->isTerminated()) {
80601 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
80602 }
80603 }
80604 }
80605 <?php
80606
80607
80608
80609
80610
80611
80612
80613
80614
80615
80616 namespace Symfony\Component\Process;
80617
80618 use Symfony\Component\Process\Exception\InvalidArgumentException;
80619 use Symfony\Component\Process\Exception\LogicException;
80620
80621
80622
80623
80624 class ProcessBuilder
80625 {
80626 private $arguments;
80627 private $cwd;
80628 private $env = array();
80629 private $input;
80630 private $timeout = 60;
80631 private $options = array();
80632 private $inheritEnv = true;
80633 private $prefix = array();
80634 private $outputDisabled = false;
80635
80636
80637
80638
80639 public function __construct(array $arguments = array())
80640 {
80641 $this->arguments = $arguments;
80642 }
80643
80644
80645
80646
80647
80648
80649
80650
80651 public static function create(array $arguments = array())
80652 {
80653 return new static($arguments);
80654 }
80655
80656
80657
80658
80659
80660
80661
80662
80663 public function add($argument)
80664 {
80665 $this->arguments[] = $argument;
80666
80667 return $this;
80668 }
80669
80670
80671
80672
80673
80674
80675
80676
80677
80678
80679 public function setPrefix($prefix)
80680 {
80681 $this->prefix = \is_array($prefix) ? $prefix : array($prefix);
80682
80683 return $this;
80684 }
80685
80686
80687
80688
80689
80690
80691
80692
80693
80694
80695
80696 public function setArguments(array $arguments)
80697 {
80698 $this->arguments = $arguments;
80699
80700 return $this;
80701 }
80702
80703
80704
80705
80706
80707
80708
80709
80710 public function setWorkingDirectory($cwd)
80711 {
80712 $this->cwd = $cwd;
80713
80714 return $this;
80715 }
80716
80717
80718
80719
80720
80721
80722
80723
80724 public function inheritEnvironmentVariables($inheritEnv = true)
80725 {
80726 $this->inheritEnv = $inheritEnv;
80727
80728 return $this;
80729 }
80730
80731
80732
80733
80734
80735
80736
80737
80738
80739
80740
80741
80742 public function setEnv($name, $value)
80743 {
80744 $this->env[$name] = $value;
80745
80746 return $this;
80747 }
80748
80749
80750
80751
80752
80753
80754
80755
80756
80757
80758
80759
80760 public function addEnvironmentVariables(array $variables)
80761 {
80762 $this->env = array_replace($this->env, $variables);
80763
80764 return $this;
80765 }
80766
80767
80768
80769
80770
80771
80772
80773
80774
80775
80776
80777
80778 public function setInput($input)
80779 {
80780 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
80781
80782 return $this;
80783 }
80784
80785
80786
80787
80788
80789
80790
80791
80792
80793
80794
80795
80796 public function setTimeout($timeout)
80797 {
80798 if (null === $timeout) {
80799 $this->timeout = null;
80800
80801 return $this;
80802 }
80803
80804 $timeout = (float) $timeout;
80805
80806 if ($timeout < 0) {
80807 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
80808 }
80809
80810 $this->timeout = $timeout;
80811
80812 return $this;
80813 }
80814
80815
80816
80817
80818
80819
80820
80821
80822
80823 public function setOption($name, $value)
80824 {
80825 $this->options[$name] = $value;
80826
80827 return $this;
80828 }
80829
80830
80831
80832
80833
80834
80835 public function disableOutput()
80836 {
80837 $this->outputDisabled = true;
80838
80839 return $this;
80840 }
80841
80842
80843
80844
80845
80846
80847 public function enableOutput()
80848 {
80849 $this->outputDisabled = false;
80850
80851 return $this;
80852 }
80853
80854
80855
80856
80857
80858
80859
80860
80861 public function getProcess()
80862 {
80863 if (0 === \count($this->prefix) && 0 === \count($this->arguments)) {
80864 throw new LogicException('You must add() command arguments before calling getProcess().');
80865 }
80866
80867 $options = $this->options;
80868
80869 $arguments = array_merge($this->prefix, $this->arguments);
80870 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
80871
80872 if ($this->inheritEnv) {
80873
80874 $env = array_replace($_ENV, $_SERVER, $this->env);
80875 } else {
80876 $env = $this->env;
80877 }
80878
80879 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
80880
80881 if ($this->outputDisabled) {
80882 $process->disableOutput();
80883 }
80884
80885 return $process;
80886 }
80887 }
80888 <?php
80889
80890
80891
80892
80893
80894
80895
80896
80897
80898
80899 namespace Symfony\Component\Process;
80900
80901 use Symfony\Component\Process\Exception\InvalidArgumentException;
80902
80903
80904
80905
80906
80907
80908
80909
80910 class ProcessUtils
80911 {
80912
80913
80914
80915 private function __construct()
80916 {
80917 }
80918
80919
80920
80921
80922
80923
80924
80925
80926 public static function escapeArgument($argument)
80927 {
80928
80929
80930
80931
80932 if ('\\' === \DIRECTORY_SEPARATOR) {
80933 if ('' === $argument) {
80934 return escapeshellarg($argument);
80935 }
80936
80937 $escapedArgument = '';
80938 $quote = false;
80939 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
80940 if ('"' === $part) {
80941 $escapedArgument .= '\\"';
80942 } elseif (self::isSurroundedBy($part, '%')) {
80943
80944 $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
80945 } else {
80946
80947 if ('\\' === substr($part, -1)) {
80948 $part .= '\\';
80949 }
80950 $quote = true;
80951 $escapedArgument .= $part;
80952 }
80953 }
80954 if ($quote) {
80955 $escapedArgument = '"'.$escapedArgument.'"';
80956 }
80957
80958 return $escapedArgument;
80959 }
80960
80961 return "'".str_replace("'", "'\\''", $argument)."'";
80962 }
80963
80964
80965
80966
80967
80968
80969
80970
80971
80972
80973
80974
80975
80976 public static function validateInput($caller, $input)
80977 {
80978 if (null !== $input) {
80979 if (\is_resource($input)) {
80980 return $input;
80981 }
80982 if (\is_string($input)) {
80983 return $input;
80984 }
80985 if (is_scalar($input)) {
80986 return (string) $input;
80987 }
80988
80989 if (\is_object($input) && method_exists($input, '__toString')) {
80990 @trigger_error('Passing an object as an input is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
80991
80992 return (string) $input;
80993 }
80994
80995 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
80996 }
80997
80998 return $input;
80999 }
81000
81001 private static function isSurroundedBy($arg, $char)
81002 {
81003 return 2 < \strlen($arg) && $char === $arg[0] && $char === $arg[\strlen($arg) - 1];
81004 }
81005 }
81006 Copyright (c) 2011 Jordi Boggiano
81007
81008 Permission is hereby granted, free of charge, to any person obtaining a copy
81009 of this software and associated documentation files (the "Software"), to deal
81010 in the Software without restriction, including without limitation the rights
81011 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
81012 copies of the Software, and to permit persons to whom the Software is furnished
81013 to do so, subject to the following conditions:
81014
81015 The above copyright notice and this permission notice shall be included in all
81016 copies or substantial portions of the Software.
81017
81018 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81019 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81020 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81021 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81022 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81023 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
81024 THE SOFTWARE.
81025 <?php
81026
81027
81028
81029
81030
81031
81032
81033
81034
81035
81036 namespace Seld\JsonLint;
81037
81038 class DuplicateKeyException extends ParsingException
81039 {
81040
81041
81042
81043
81044
81045 public function __construct($message, $key, array $details = array())
81046 {
81047 $details['key'] = $key;
81048 parent::__construct($message, $details);
81049 }
81050
81051 public function getKey()
81052 {
81053 return $this->details['key'];
81054 }
81055
81056
81057
81058
81059 public function getDetails()
81060 {
81061 return $this->details;
81062 }
81063 }
81064 <?php
81065
81066
81067
81068
81069
81070
81071
81072
81073
81074
81075 namespace Seld\JsonLint;
81076 use stdClass;
81077
81078
81079
81080
81081
81082
81083
81084
81085
81086
81087
81088
81089
81090
81091 class JsonParser
81092 {
81093 const DETECT_KEY_CONFLICTS = 1;
81094 const ALLOW_DUPLICATE_KEYS = 2;
81095 const PARSE_TO_ASSOC = 4;
81096
81097 private $lexer;
81098
81099 private $flags;
81100 private $stack;
81101 private $vstack; 
81102 private $lstack; 
81103
81104
81105
81106
81107 private $symbols = array(
81108 'error' => 2,
81109 'JSONString' => 3,
81110 'STRING' => 4,
81111 'JSONNumber' => 5,
81112 'NUMBER' => 6,
81113 'JSONNullLiteral' => 7,
81114 'NULL' => 8,
81115 'JSONBooleanLiteral' => 9,
81116 'TRUE' => 10,
81117 'FALSE' => 11,
81118 'JSONText' => 12,
81119 'JSONValue' => 13,
81120 'EOF' => 14,
81121 'JSONObject' => 15,
81122 'JSONArray' => 16,
81123 '{' => 17,
81124 '}' => 18,
81125 'JSONMemberList' => 19,
81126 'JSONMember' => 20,
81127 ':' => 21,
81128 ',' => 22,
81129 '[' => 23,
81130 ']' => 24,
81131 'JSONElementList' => 25,
81132 '$accept' => 0,
81133 '$end' => 1,
81134 );
81135
81136
81137
81138
81139 private $terminals_ = array(
81140 2 => "error",
81141 4 => "STRING",
81142 6 => "NUMBER",
81143 8 => "NULL",
81144 10 => "TRUE",
81145 11 => "FALSE",
81146 14 => "EOF",
81147 17 => "{",
81148 18 => "}",
81149 21 => ":",
81150 22 => ",",
81151 23 => "[",
81152 24 => "]",
81153 );
81154
81155 private $productions_ = array(
81156 0,
81157 array(3, 1),
81158 array(5, 1),
81159 array(7, 1),
81160 array(9, 1),
81161 array(9, 1),
81162 array(12, 2),
81163 array(13, 1),
81164 array(13, 1),
81165 array(13, 1),
81166 array(13, 1),
81167 array(13, 1),
81168 array(13, 1),
81169 array(15, 2),
81170 array(15, 3),
81171 array(20, 3),
81172 array(19, 1),
81173 array(19, 3),
81174 array(16, 2),
81175 array(16, 3),
81176 array(25, 1),
81177 array(25, 3)
81178 );
81179
81180 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)),
81181 );
81182
81183 private $defaultActions = array(
81184 16 => array(2, 6)
81185 );
81186
81187
81188
81189
81190
81191
81192 public function lint($input, $flags = 0)
81193 {
81194 try {
81195 $this->parse($input, $flags);
81196 } catch (ParsingException $e) {
81197 return $e;
81198 }
81199 return null;
81200 }
81201
81202
81203
81204
81205
81206
81207
81208 public function parse($input, $flags = 0)
81209 {
81210 $this->failOnBOM($input);
81211
81212 $this->flags = $flags;
81213
81214 $this->stack = array(0);
81215 $this->vstack = array(null);
81216 $this->lstack = array();
81217
81218 $yytext = '';
81219 $yylineno = 0;
81220 $yyleng = 0;
81221 $recovering = 0;
81222 $TERROR = 2;
81223 $EOF = 1;
81224
81225 $this->lexer = new Lexer();
81226 $this->lexer->setInput($input);
81227
81228 $yyloc = $this->lexer->yylloc;
81229 $this->lstack[] = $yyloc;
81230
81231 $symbol = null;
81232 $preErrorSymbol = null;
81233 $state = null;
81234 $action = null;
81235 $a = null;
81236 $r = null;
81237 $yyval = new stdClass;
81238 $p = null;
81239 $len = null;
81240 $newState = null;
81241 $expected = null;
81242 $errStr = null;
81243
81244 while (true) {
81245
81246 $state = $this->stack[\count($this->stack)-1];
81247
81248
81249 if (isset($this->defaultActions[$state])) {
81250 $action = $this->defaultActions[$state];
81251 } else {
81252 if ($symbol == null) {
81253 $symbol = $this->lex();
81254 }
81255
81256 $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
81257 }
81258
81259
81260 if (!$action || !$action[0]) {
81261 if (!$recovering) {
81262
81263 $expected = array();
81264 foreach ($this->table[$state] as $p => $ignore) {
81265 if (isset($this->terminals_[$p]) && $p > 2) {
81266 $expected[] = "'" . $this->terminals_[$p] . "'";
81267 }
81268 }
81269
81270 $message = null;
81271 if (\in_array("'STRING'", $expected) && \in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
81272 $message = "Invalid string";
81273 if ("'" === substr($this->lexer->match, 0, 1)) {
81274 $message .= ", it appears you used single quotes instead of double quotes";
81275 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u](...)?)}', $this->lexer->getFullUpcomingInput(), $match)) {
81276 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
81277 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getFullUpcomingInput())) {
81278 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
81279 }
81280 }
81281
81282 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
81283 $errStr .= $this->lexer->showPosition() . "\n";
81284 if ($message) {
81285 $errStr .= $message;
81286 } else {
81287 $errStr .= (\count($expected) > 1) ? "Expected one of: " : "Expected: ";
81288 $errStr .= implode(', ', $expected);
81289 }
81290
81291 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
81292 $errStr .= " - It appears you have an extra trailing comma";
81293 }
81294
81295 $this->parseError($errStr, array(
81296 'text' => $this->lexer->match,
81297 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
81298 'line' => $this->lexer->yylineno,
81299 'loc' => $yyloc,
81300 'expected' => $expected,
81301 ));
81302 }
81303
81304
81305 if ($recovering == 3) {
81306 if ($symbol == $EOF) {
81307 throw new ParsingException($errStr ?: 'Parsing halted.');
81308 }
81309
81310
81311 $yyleng = $this->lexer->yyleng;
81312 $yytext = $this->lexer->yytext;
81313 $yylineno = $this->lexer->yylineno;
81314 $yyloc = $this->lexer->yylloc;
81315 $symbol = $this->lex();
81316 }
81317
81318
81319 while (true) {
81320
81321 if (\array_key_exists($TERROR, $this->table[$state])) {
81322 break;
81323 }
81324 if ($state == 0) {
81325 throw new ParsingException($errStr ?: 'Parsing halted.');
81326 }
81327 $this->popStack(1);
81328 $state = $this->stack[\count($this->stack)-1];
81329 }
81330
81331 $preErrorSymbol = $symbol; 
81332 $symbol = $TERROR; 
81333 $state = $this->stack[\count($this->stack)-1];
81334 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
81335 $recovering = 3; 
81336 }
81337
81338
81339 if (\is_array($action[0]) && \count($action) > 1) {
81340 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
81341 }
81342
81343 switch ($action[0]) {
81344 case 1: 
81345 $this->stack[] = $symbol;
81346 $this->vstack[] = $this->lexer->yytext;
81347 $this->lstack[] = $this->lexer->yylloc;
81348 $this->stack[] = $action[1]; 
81349 $symbol = null;
81350 if (!$preErrorSymbol) { 
81351 $yyleng = $this->lexer->yyleng;
81352 $yytext = $this->lexer->yytext;
81353 $yylineno = $this->lexer->yylineno;
81354 $yyloc = $this->lexer->yylloc;
81355 if ($recovering > 0) {
81356 $recovering--;
81357 }
81358 } else { 
81359 $symbol = $preErrorSymbol;
81360 $preErrorSymbol = null;
81361 }
81362 break;
81363
81364 case 2: 
81365 $len = $this->productions_[$action[1]][1];
81366
81367
81368 $yyval->token = $this->vstack[\count($this->vstack) - $len]; 
81369
81370 $yyval->store = array( 
81371 'first_line' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_line'],
81372 'last_line' => $this->lstack[\count($this->lstack) - 1]['last_line'],
81373 'first_column' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_column'],
81374 'last_column' => $this->lstack[\count($this->lstack) - 1]['last_column'],
81375 );
81376 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack);
81377
81378 if (!$r instanceof Undefined) {
81379 return $r;
81380 }
81381
81382 if ($len) {
81383 $this->popStack($len);
81384 }
81385
81386 $this->stack[] = $this->productions_[$action[1]][0]; 
81387 $this->vstack[] = $yyval->token;
81388 $this->lstack[] = $yyval->store;
81389 $newState = $this->table[$this->stack[\count($this->stack)-2]][$this->stack[\count($this->stack)-1]];
81390 $this->stack[] = $newState;
81391 break;
81392
81393 case 3: 
81394
81395 return true;
81396 }
81397 }
81398 }
81399
81400 protected function parseError($str, $hash)
81401 {
81402 throw new ParsingException($str, $hash);
81403 }
81404
81405
81406
81407
81408 private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
81409 {
81410
81411 $len = \count($tokens) - 1;
81412 switch ($yystate) {
81413 case 1:
81414 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
81415 $yyval->token = $yytext;
81416 break;
81417 case 2:
81418 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
81419 $yyval->token = \floatval($yytext);
81420 } else {
81421 $yyval->token = strpos($yytext, '.') === false ? \intval($yytext) : \floatval($yytext);
81422 }
81423 break;
81424 case 3:
81425 $yyval->token = null;
81426 break;
81427 case 4:
81428 $yyval->token = true;
81429 break;
81430 case 5:
81431 $yyval->token = false;
81432 break;
81433 case 6:
81434 return $yyval->token = $tokens[$len-1];
81435 case 13:
81436 if ($this->flags & self::PARSE_TO_ASSOC) {
81437 $yyval->token = array();
81438 } else {
81439 $yyval->token = new stdClass;
81440 }
81441 break;
81442 case 14:
81443 $yyval->token = $tokens[$len-1];
81444 break;
81445 case 15:
81446 $yyval->token = array($tokens[$len-2], $tokens[$len]);
81447 break;
81448 case 16:
81449 if (PHP_VERSION_ID < 70100) {
81450 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
81451 } else {
81452 $property = $tokens[$len][0];
81453 }
81454 if ($this->flags & self::PARSE_TO_ASSOC) {
81455 $yyval->token = array();
81456 $yyval->token[$property] = $tokens[$len][1];
81457 } else {
81458 $yyval->token = new stdClass;
81459 $yyval->token->$property = $tokens[$len][1];
81460 }
81461 break;
81462 case 17:
81463 if ($this->flags & self::PARSE_TO_ASSOC) {
81464 $yyval->token =& $tokens[$len-2];
81465 $key = $tokens[$len][0];
81466 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
81467 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
81468 $errStr .= $this->lexer->showPosition() . "\n";
81469 $errStr .= "Duplicate key: ".$tokens[$len][0];
81470 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
81471 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
81472 $duplicateCount = 1;
81473 do {
81474 $duplicateKey = $key . '.' . $duplicateCount++;
81475 } while (isset($tokens[$len-2][$duplicateKey]));
81476 $key = $duplicateKey;
81477 }
81478 $tokens[$len-2][$key] = $tokens[$len][1];
81479 } else {
81480 $yyval->token = $tokens[$len-2];
81481 if (PHP_VERSION_ID < 70100) {
81482 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
81483 } else {
81484 $key = $tokens[$len][0];
81485 }
81486 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
81487 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
81488 $errStr .= $this->lexer->showPosition() . "\n";
81489 $errStr .= "Duplicate key: ".$tokens[$len][0];
81490 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
81491 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
81492 $duplicateCount = 1;
81493 do {
81494 $duplicateKey = $key . '.' . $duplicateCount++;
81495 } while (isset($tokens[$len-2]->$duplicateKey));
81496 $key = $duplicateKey;
81497 }
81498 $tokens[$len-2]->$key = $tokens[$len][1];
81499 }
81500 break;
81501 case 18:
81502 $yyval->token = array();
81503 break;
81504 case 19:
81505 $yyval->token = $tokens[$len-1];
81506 break;
81507 case 20:
81508 $yyval->token = array($tokens[$len]);
81509 break;
81510 case 21:
81511 $tokens[$len-2][] = $tokens[$len];
81512 $yyval->token = $tokens[$len-2];
81513 break;
81514 }
81515
81516 return new Undefined();
81517 }
81518
81519 private function stringInterpolation($match)
81520 {
81521 switch ($match[0]) {
81522 case '\\\\':
81523 return '\\';
81524 case '\"':
81525 return '"';
81526 case '\b':
81527 return \chr(8);
81528 case '\f':
81529 return \chr(12);
81530 case '\n':
81531 return "\n";
81532 case '\r':
81533 return "\r";
81534 case '\t':
81535 return "\t";
81536 case '\/':
81537 return "/";
81538 default:
81539 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', ENT_QUOTES, 'UTF-8');
81540 }
81541 }
81542
81543 private function popStack($n)
81544 {
81545 $this->stack = \array_slice($this->stack, 0, - (2 * $n));
81546 $this->vstack = \array_slice($this->vstack, 0, - $n);
81547 $this->lstack = \array_slice($this->lstack, 0, - $n);
81548 }
81549
81550 private function lex()
81551 {
81552 $token = $this->lexer->lex() ?: 1; 
81553
81554 if (!is_numeric($token)) {
81555 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
81556 }
81557
81558 return $token;
81559 }
81560
81561 private function failOnBOM($input)
81562 {
81563
81564 $bom = "\xEF\xBB\xBF";
81565
81566 if (substr($input, 0, 3) === $bom) {
81567 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
81568 }
81569 }
81570 }
81571 <?php
81572
81573
81574
81575
81576
81577
81578
81579
81580
81581
81582 namespace Seld\JsonLint;
81583
81584
81585
81586
81587
81588
81589 class Lexer
81590 {
81591 private $EOF = 1;
81592
81593
81594
81595 private $rules = array(
81596 0 => '/\G\s+/',
81597 1 => '/\G-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
81598 2 => '{\G"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
81599 3 => '/\G\{/',
81600 4 => '/\G\}/',
81601 5 => '/\G\[/',
81602 6 => '/\G\]/',
81603 7 => '/\G,/',
81604 8 => '/\G:/',
81605 9 => '/\Gtrue\b/',
81606 10 => '/\Gfalse\b/',
81607 11 => '/\Gnull\b/',
81608 12 => '/\G$/',
81609 13 => '/\G./',
81610 );
81611
81612 private $conditions = array(
81613 "INITIAL" => array(
81614 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
81615 "inclusive" => true,
81616 ),
81617 );
81618
81619 private $conditionStack;
81620 private $input;
81621 private $more;
81622 private $done;
81623 private $offset;
81624
81625 public $match;
81626 public $yylineno;
81627 public $yyleng;
81628 public $yytext;
81629 public $yylloc;
81630
81631 public function lex()
81632 {
81633 $r = $this->next();
81634 if (!$r instanceof Undefined) {
81635 return $r;
81636 }
81637
81638 return $this->lex();
81639 }
81640
81641 public function setInput($input)
81642 {
81643 $this->input = $input;
81644 $this->more = false;
81645 $this->done = false;
81646 $this->offset = 0;
81647 $this->yylineno = $this->yyleng = 0;
81648 $this->yytext = $this->match = '';
81649 $this->conditionStack = array('INITIAL');
81650 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
81651
81652 return $this;
81653 }
81654
81655 public function showPosition()
81656 {
81657 $pre = str_replace("\n", '', $this->getPastInput());
81658 $c = str_repeat('-', max(0, \strlen($pre) - 1)); 
81659
81660 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
81661 }
81662
81663 public function getPastInput()
81664 {
81665 $pastLength = $this->offset - \strlen($this->match);
81666
81667 return ($pastLength > 20 ? '...' : '') . substr($this->input, max(0, $pastLength - 20), min(20, $pastLength));
81668 }
81669
81670 public function getUpcomingInput()
81671 {
81672 $next = $this->match;
81673 if (\strlen($next) < 20) {
81674 $next .= substr($this->input, $this->offset, 20 - \strlen($next));
81675 }
81676
81677 return substr($next, 0, 20) . (\strlen($next) > 20 ? '...' : '');
81678 }
81679
81680 public function getFullUpcomingInput()
81681 {
81682 $next = $this->match;
81683 if (substr($next, 0, 1) === '"' && substr_count($next, '"') === 1) {
81684 $len = \strlen($this->input);
81685 $strEnd = min(strpos($this->input, '"', $this->offset + 1) ?: $len, strpos($this->input, "\n", $this->offset + 1) ?: $len);
81686 $next .= substr($this->input, $this->offset, $strEnd - $this->offset);
81687 } elseif (\strlen($next) < 20) {
81688 $next .= substr($this->input, $this->offset, 20 - \strlen($next));
81689 }
81690
81691 return $next;
81692 }
81693
81694 protected function parseError($str, $hash)
81695 {
81696 throw new \Exception($str);
81697 }
81698
81699 private function next()
81700 {
81701 if ($this->done) {
81702 return $this->EOF;
81703 }
81704 if ($this->offset === \strlen($this->input)) {
81705 $this->done = true;
81706 }
81707
81708 $token = null;
81709 $match = null;
81710 $col = null;
81711 $lines = null;
81712
81713 if (!$this->more) {
81714 $this->yytext = '';
81715 $this->match = '';
81716 }
81717
81718 $rules = $this->getCurrentRules();
81719 $rulesLen = \count($rules);
81720
81721 for ($i=0; $i < $rulesLen; $i++) {
81722 if (preg_match($this->rules[$rules[$i]], $this->input, $match, 0, $this->offset)) {
81723 preg_match_all('/\n.*/', $match[0], $lines);
81724 $lines = $lines[0];
81725 if ($lines) {
81726 $this->yylineno += \count($lines);
81727 }
81728
81729 $this->yylloc = array(
81730 'first_line' => $this->yylloc['last_line'],
81731 'last_line' => $this->yylineno+1,
81732 'first_column' => $this->yylloc['last_column'],
81733 'last_column' => $lines ? \strlen($lines[\count($lines) - 1]) - 1 : $this->yylloc['last_column'] + \strlen($match[0]),
81734 );
81735 $this->yytext .= $match[0];
81736 $this->match .= $match[0];
81737 $this->yyleng = \strlen($this->yytext);
81738 $this->more = false;
81739 $this->offset += \strlen($match[0]);
81740 $token = $this->performAction($rules[$i], $this->conditionStack[\count($this->conditionStack)-1]);
81741 if ($token) {
81742 return $token;
81743 }
81744
81745 return new Undefined();
81746 }
81747 }
81748
81749 if ($this->offset === \strlen($this->input)) {
81750 return $this->EOF;
81751 }
81752
81753 $this->parseError(
81754 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
81755 array(
81756 'text' => "",
81757 'token' => null,
81758 'line' => $this->yylineno,
81759 )
81760 );
81761 }
81762
81763 private function getCurrentRules()
81764 {
81765 return $this->conditions[$this->conditionStack[\count($this->conditionStack)-1]]['rules'];
81766 }
81767
81768 private function performAction($avoiding_name_collisions, $YY_START)
81769 {
81770 switch ($avoiding_name_collisions) {
81771 case 0:
81772 break;
81773 case 1:
81774 return 6;
81775 case 2:
81776 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
81777
81778 return 4;
81779 case 3:
81780 return 17;
81781 case 4:
81782 return 18;
81783 case 5:
81784 return 23;
81785 case 6:
81786 return 24;
81787 case 7:
81788 return 22;
81789 case 8:
81790 return 21;
81791 case 9:
81792 return 10;
81793 case 10:
81794 return 11;
81795 case 11:
81796 return 8;
81797 case 12:
81798 return 14;
81799 case 13:
81800 return 'INVALID';
81801 }
81802 }
81803 }
81804 <?php
81805
81806
81807
81808
81809
81810
81811
81812
81813
81814
81815 namespace Seld\JsonLint;
81816
81817 class ParsingException extends \Exception
81818 {
81819 protected $details;
81820
81821
81822
81823
81824
81825 public function __construct($message, $details = array())
81826 {
81827 $this->details = $details;
81828 parent::__construct($message);
81829 }
81830
81831
81832
81833
81834 public function getDetails()
81835 {
81836 return $this->details;
81837 }
81838 }
81839 <?php
81840
81841
81842
81843
81844
81845
81846
81847
81848
81849
81850 namespace Seld\JsonLint;
81851
81852 class Undefined
81853 {
81854 }
81855 MIT License
81856
81857 Copyright (c) 2016
81858
81859 Permission is hereby granted, free of charge, to any person obtaining a copy
81860 of this software and associated documentation files (the "Software"), to deal
81861 in the Software without restriction, including without limitation the rights
81862 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
81863 copies of the Software, and to permit persons to whom the Software is
81864 furnished to do so, subject to the following conditions:
81865
81866 The above copyright notice and this permission notice shall be included in all
81867 copies or substantial portions of the Software.
81868
81869 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81870 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81871 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81872 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81873 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81874 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81875 SOFTWARE.
81876 <?php
81877
81878 require __DIR__ . '/../vendor/autoload.php';
81879
81880 $data = json_decode(file_get_contents('data.json'));
81881
81882
81883 $validator = new JsonSchema\Validator();
81884 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
81885
81886 if ($validator->isValid()) {
81887 echo "The supplied JSON validates against the schema.\n";
81888 } else {
81889 echo "JSON does not validate. Violations:\n";
81890 foreach ($validator->getErrors() as $error) {
81891 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
81892 }
81893 }
81894 <?php
81895
81896
81897
81898
81899
81900
81901
81902
81903 namespace JsonSchema\Constraints;
81904
81905 use JsonSchema\Entity\JsonPointer;
81906 use JsonSchema\Exception\InvalidArgumentException;
81907 use JsonSchema\Exception\ValidationException;
81908 use JsonSchema\Validator;
81909
81910
81911
81912
81913
81914 class BaseConstraint
81915 {
81916
81917
81918
81919 protected $errors = array();
81920
81921
81922
81923
81924 protected $errorMask = Validator::ERROR_NONE;
81925
81926
81927
81928
81929 protected $factory;
81930
81931
81932
81933
81934 public function __construct(Factory $factory = null)
81935 {
81936 $this->factory = $factory ?: new Factory();
81937 }
81938
81939 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
81940 {
81941 $error = array(
81942 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
81943 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
81944 'message' => $message,
81945 'constraint' => $constraint,
81946 'context' => $this->factory->getErrorContext(),
81947 );
81948
81949 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
81950 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
81951 }
81952
81953 if (is_array($more) && count($more) > 0) {
81954 $error += $more;
81955 }
81956
81957 $this->errors[] = $error;
81958 $this->errorMask |= $error['context'];
81959 }
81960
81961 public function addErrors(array $errors)
81962 {
81963 if ($errors) {
81964 $this->errors = array_merge($this->errors, $errors);
81965 $errorMask = &$this->errorMask;
81966 array_walk($errors, function ($error) use (&$errorMask) {
81967 if (isset($error['context'])) {
81968 $errorMask |= $error['context'];
81969 }
81970 });
81971 }
81972 }
81973
81974 public function getErrors($errorContext = Validator::ERROR_ALL)
81975 {
81976 if ($errorContext === Validator::ERROR_ALL) {
81977 return $this->errors;
81978 }
81979
81980 return array_filter($this->errors, function ($error) use ($errorContext) {
81981 if ($errorContext & $error['context']) {
81982 return true;
81983 }
81984 });
81985 }
81986
81987 public function numErrors($errorContext = Validator::ERROR_ALL)
81988 {
81989 if ($errorContext === Validator::ERROR_ALL) {
81990 return count($this->errors);
81991 }
81992
81993 return count($this->getErrors($errorContext));
81994 }
81995
81996 public function isValid()
81997 {
81998 return !$this->getErrors();
81999 }
82000
82001
82002
82003
82004
82005 public function reset()
82006 {
82007 $this->errors = array();
82008 $this->errorMask = Validator::ERROR_NONE;
82009 }
82010
82011
82012
82013
82014
82015
82016 public function getErrorMask()
82017 {
82018 return $this->errorMask;
82019 }
82020
82021
82022
82023
82024
82025
82026
82027
82028 public static function arrayToObjectRecursive($array)
82029 {
82030 $json = json_encode($array);
82031 if (json_last_error() !== \JSON_ERROR_NONE) {
82032 $message = 'Unable to encode schema array as JSON';
82033 if (function_exists('json_last_error_msg')) {
82034 $message .= ': ' . json_last_error_msg();
82035 }
82036 throw new InvalidArgumentException($message);
82037 }
82038
82039 return (object) json_decode($json);
82040 }
82041 }
82042 <?php
82043
82044
82045
82046
82047
82048
82049
82050
82051 namespace JsonSchema\Constraints;
82052
82053 use JsonSchema\Entity\JsonPointer;
82054
82055
82056
82057
82058
82059
82060
82061 class CollectionConstraint extends Constraint
82062 {
82063
82064
82065
82066 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
82067 {
82068
82069 if (isset($schema->minItems) && count($value) < $schema->minItems) {
82070 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
82071 }
82072
82073
82074 if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
82075 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
82076 }
82077
82078
82079 if (isset($schema->uniqueItems) && $schema->uniqueItems) {
82080 $unique = $value;
82081 if (is_array($value) && count($value)) {
82082 $unique = array_map(function ($e) {
82083 return var_export($e, true);
82084 }, $value);
82085 }
82086 if (count(array_unique($unique)) != count($value)) {
82087 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
82088 }
82089 }
82090
82091
82092 if (isset($schema->items)) {
82093 $this->validateItems($value, $schema, $path, $i);
82094 }
82095 }
82096
82097
82098
82099
82100
82101
82102
82103
82104
82105 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
82106 {
82107 if (is_object($schema->items)) {
82108
82109 foreach ($value as $k => &$v) {
82110 $initErrors = $this->getErrors();
82111
82112
82113 $this->checkUndefined($v, $schema->items, $path, $k);
82114
82115
82116 if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
82117 $secondErrors = $this->getErrors();
82118 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
82119 }
82120
82121
82122 if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
82123 $this->errors = $secondErrors;
82124 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
82125 $this->errors = $initErrors;
82126 }
82127 }
82128 unset($v); 
82129
82130 } else {
82131
82132 foreach ($value as $k => &$v) {
82133 if (array_key_exists($k, $schema->items)) {
82134 $this->checkUndefined($v, $schema->items[$k], $path, $k);
82135 } else {
82136
82137 if (property_exists($schema, 'additionalItems')) {
82138 if ($schema->additionalItems !== false) {
82139 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
82140 } else {
82141 $this->addError(
82142 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
82143 }
82144 } else {
82145
82146 $this->checkUndefined($v, new \stdClass(), $path, $k);
82147 }
82148 }
82149 }
82150 unset($v); 
82151
82152
82153
82154 if (count($value) > 0) {
82155 for ($k = count($value); $k < count($schema->items); $k++) {
82156 $undefinedInstance = $this->factory->createInstanceFor('undefined');
82157 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
82158 }
82159 }
82160 }
82161 }
82162 }
82163 <?php
82164
82165
82166
82167
82168
82169
82170
82171
82172 namespace JsonSchema\Constraints;
82173
82174 use JsonSchema\Entity\JsonPointer;
82175
82176
82177
82178
82179
82180
82181
82182 abstract class Constraint extends BaseConstraint implements ConstraintInterface
82183 {
82184 protected $inlineSchemaProperty = '$schema';
82185
82186 const CHECK_MODE_NONE = 0x00000000;
82187 const CHECK_MODE_NORMAL = 0x00000001;
82188 const CHECK_MODE_TYPE_CAST = 0x00000002;
82189 const CHECK_MODE_COERCE_TYPES = 0x00000004;
82190 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
82191 const CHECK_MODE_EXCEPTIONS = 0x00000010;
82192 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
82193 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
82194 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
82195
82196
82197
82198
82199
82200
82201
82202
82203
82204 protected function incrementPath(JsonPointer $path = null, $i)
82205 {
82206 $path = $path ?: new JsonPointer('');
82207
82208 if ($i === null || $i === '') {
82209 return $path;
82210 }
82211
82212 $path = $path->withPropertyPaths(
82213 array_merge(
82214 $path->getPropertyPaths(),
82215 array($i)
82216 )
82217 );
82218
82219 return $path;
82220 }
82221
82222
82223
82224
82225
82226
82227
82228
82229
82230 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
82231 {
82232 $validator = $this->factory->createInstanceFor('collection');
82233 $validator->check($value, $schema, $path, $i);
82234
82235 $this->addErrors($validator->getErrors());
82236 }
82237
82238
82239
82240
82241
82242
82243
82244
82245
82246
82247
82248 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
82249 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
82250 {
82251 $validator = $this->factory->createInstanceFor('object');
82252 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
82253
82254 $this->addErrors($validator->getErrors());
82255 }
82256
82257
82258
82259
82260
82261
82262
82263
82264
82265 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
82266 {
82267 $validator = $this->factory->createInstanceFor('type');
82268 $validator->check($value, $schema, $path, $i);
82269
82270 $this->addErrors($validator->getErrors());
82271 }
82272
82273
82274
82275
82276
82277
82278
82279
82280
82281 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
82282 {
82283 $validator = $this->factory->createInstanceFor('undefined');
82284
82285 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
82286
82287 $this->addErrors($validator->getErrors());
82288 }
82289
82290
82291
82292
82293
82294
82295
82296
82297
82298 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
82299 {
82300 $validator = $this->factory->createInstanceFor('string');
82301 $validator->check($value, $schema, $path, $i);
82302
82303 $this->addErrors($validator->getErrors());
82304 }
82305
82306
82307
82308
82309
82310
82311
82312
82313
82314 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
82315 {
82316 $validator = $this->factory->createInstanceFor('number');
82317 $validator->check($value, $schema, $path, $i);
82318
82319 $this->addErrors($validator->getErrors());
82320 }
82321
82322
82323
82324
82325
82326
82327
82328
82329
82330 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
82331 {
82332 $validator = $this->factory->createInstanceFor('enum');
82333 $validator->check($value, $schema, $path, $i);
82334
82335 $this->addErrors($validator->getErrors());
82336 }
82337
82338
82339
82340
82341
82342
82343
82344
82345
82346 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
82347 {
82348 $validator = $this->factory->createInstanceFor('format');
82349 $validator->check($value, $schema, $path, $i);
82350
82351 $this->addErrors($validator->getErrors());
82352 }
82353
82354
82355
82356
82357
82358
82359 protected function getTypeCheck()
82360 {
82361 return $this->factory->getTypeCheck();
82362 }
82363
82364
82365
82366
82367
82368
82369 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
82370 {
82371 $result = array_map(
82372 function ($path) {
82373 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
82374 },
82375 $pointer->getPropertyPaths()
82376 );
82377
82378 return trim(implode('', $result), '.');
82379 }
82380 }
82381 <?php
82382
82383
82384
82385
82386
82387
82388
82389
82390 namespace JsonSchema\Constraints;
82391
82392 use JsonSchema\Entity\JsonPointer;
82393
82394
82395
82396
82397
82398
82399 interface ConstraintInterface
82400 {
82401
82402
82403
82404
82405
82406 public function getErrors();
82407
82408
82409
82410
82411
82412
82413 public function addErrors(array $errors);
82414
82415
82416
82417
82418
82419
82420
82421
82422
82423 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
82424
82425
82426
82427
82428
82429
82430 public function isValid();
82431
82432
82433
82434
82435
82436
82437
82438
82439
82440
82441
82442
82443
82444 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
82445 }
82446 <?php
82447
82448
82449
82450
82451
82452
82453
82454
82455 namespace JsonSchema\Constraints;
82456
82457 use JsonSchema\Entity\JsonPointer;
82458
82459
82460
82461
82462
82463
82464
82465 class EnumConstraint extends Constraint
82466 {
82467
82468
82469
82470 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
82471 {
82472
82473 if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
82474 return;
82475 }
82476 $type = gettype($element);
82477
82478 foreach ($schema->enum as $enum) {
82479 $enumType = gettype($enum);
82480 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
82481 if ((object) $element == $enum) {
82482 return;
82483 }
82484 }
82485
82486 if ($type === gettype($enum)) {
82487 if ($type == 'object') {
82488 if ($element == $enum) {
82489 return;
82490 }
82491 } elseif ($element === $enum) {
82492 return;
82493 }
82494 }
82495 }
82496
82497 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
82498 }
82499 }
82500 <?php
82501
82502
82503
82504
82505
82506
82507
82508
82509 namespace JsonSchema\Constraints;
82510
82511 use JsonSchema\Exception\InvalidArgumentException;
82512 use JsonSchema\SchemaStorage;
82513 use JsonSchema\SchemaStorageInterface;
82514 use JsonSchema\Uri\UriRetriever;
82515 use JsonSchema\UriRetrieverInterface;
82516 use JsonSchema\Validator;
82517
82518
82519
82520
82521 class Factory
82522 {
82523
82524
82525
82526 protected $schemaStorage;
82527
82528
82529
82530
82531 protected $uriRetriever;
82532
82533
82534
82535
82536 private $checkMode = Constraint::CHECK_MODE_NORMAL;
82537
82538
82539
82540
82541 private $typeCheck = array();
82542
82543
82544
82545
82546 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
82547
82548
82549
82550
82551 protected $constraintMap = array(
82552 'array' => 'JsonSchema\Constraints\CollectionConstraint',
82553 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
82554 'object' => 'JsonSchema\Constraints\ObjectConstraint',
82555 'type' => 'JsonSchema\Constraints\TypeConstraint',
82556 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
82557 'string' => 'JsonSchema\Constraints\StringConstraint',
82558 'number' => 'JsonSchema\Constraints\NumberConstraint',
82559 'enum' => 'JsonSchema\Constraints\EnumConstraint',
82560 'format' => 'JsonSchema\Constraints\FormatConstraint',
82561 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
82562 'validator' => 'JsonSchema\Validator'
82563 );
82564
82565
82566
82567
82568 private $instanceCache = array();
82569
82570
82571
82572
82573
82574
82575 public function __construct(
82576 SchemaStorageInterface $schemaStorage = null,
82577 UriRetrieverInterface $uriRetriever = null,
82578 $checkMode = Constraint::CHECK_MODE_NORMAL
82579 ) {
82580
82581 $this->setConfig($checkMode);
82582
82583 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
82584 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
82585 }
82586
82587
82588
82589
82590
82591
82592 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
82593 {
82594 $this->checkMode = $checkMode;
82595 }
82596
82597
82598
82599
82600
82601
82602 public function addConfig($options)
82603 {
82604 $this->checkMode |= $options;
82605 }
82606
82607
82608
82609
82610
82611
82612 public function removeConfig($options)
82613 {
82614 $this->checkMode &= ~$options;
82615 }
82616
82617
82618
82619
82620
82621
82622
82623
82624 public function getConfig($options = null)
82625 {
82626 if ($options === null) {
82627 return $this->checkMode;
82628 }
82629
82630 return $this->checkMode & $options;
82631 }
82632
82633
82634
82635
82636 public function getUriRetriever()
82637 {
82638 return $this->uriRetriever;
82639 }
82640
82641 public function getSchemaStorage()
82642 {
82643 return $this->schemaStorage;
82644 }
82645
82646 public function getTypeCheck()
82647 {
82648 if (!isset($this->typeCheck[$this->checkMode])) {
82649 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
82650 ? new TypeCheck\LooseTypeCheck()
82651 : new TypeCheck\StrictTypeCheck();
82652 }
82653
82654 return $this->typeCheck[$this->checkMode];
82655 }
82656
82657
82658
82659
82660
82661
82662
82663 public function setConstraintClass($name, $class)
82664 {
82665
82666 if (!class_exists($class)) {
82667 throw new InvalidArgumentException('Unknown constraint ' . $name);
82668 }
82669
82670 if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
82671 throw new InvalidArgumentException('Invalid class ' . $name);
82672 }
82673 $this->constraintMap[$name] = $class;
82674
82675 return $this;
82676 }
82677
82678
82679
82680
82681
82682
82683
82684
82685
82686
82687 public function createInstanceFor($constraintName)
82688 {
82689 if (!isset($this->constraintMap[$constraintName])) {
82690 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
82691 }
82692
82693 if (!isset($this->instanceCache[$constraintName])) {
82694 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
82695 }
82696
82697 return clone $this->instanceCache[$constraintName];
82698 }
82699
82700
82701
82702
82703
82704
82705 public function getErrorContext()
82706 {
82707 return $this->errorContext;
82708 }
82709
82710
82711
82712
82713
82714
82715 public function setErrorContext($errorContext)
82716 {
82717 $this->errorContext = $errorContext;
82718 }
82719 }
82720 <?php
82721
82722
82723
82724
82725
82726
82727
82728
82729 namespace JsonSchema\Constraints;
82730
82731 use JsonSchema\Entity\JsonPointer;
82732 use JsonSchema\Rfc3339;
82733
82734
82735
82736
82737
82738
82739
82740
82741 class FormatConstraint extends Constraint
82742 {
82743
82744
82745
82746 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
82747 {
82748 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
82749 return;
82750 }
82751
82752 switch ($schema->format) {
82753 case 'date':
82754 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
82755 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
82756 }
82757 break;
82758
82759 case 'time':
82760 if (!$this->validateDateTime($element, 'H:i:s')) {
82761 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
82762 }
82763 break;
82764
82765 case 'date-time':
82766 if (null === Rfc3339::createFromString($element)) {
82767 $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));
82768 }
82769 break;
82770
82771 case 'utc-millisec':
82772 if (!$this->validateDateTime($element, 'U')) {
82773 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
82774 }
82775 break;
82776
82777 case 'regex':
82778 if (!$this->validateRegex($element)) {
82779 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
82780 }
82781 break;
82782
82783 case 'color':
82784 if (!$this->validateColor($element)) {
82785 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
82786 }
82787 break;
82788
82789 case 'style':
82790 if (!$this->validateStyle($element)) {
82791 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
82792 }
82793 break;
82794
82795 case 'phone':
82796 if (!$this->validatePhone($element)) {
82797 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
82798 }
82799 break;
82800
82801 case 'uri':
82802 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
82803 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
82804 }
82805 break;
82806
82807 case 'uriref':
82808 case 'uri-reference':
82809 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
82810
82811
82812
82813 if (substr($element, 0, 2) === '//') { 
82814 $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
82815 } elseif (substr($element, 0, 1) === '/') { 
82816 $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
82817 } elseif (strlen($element)) { 
82818 $pathParts = explode('/', $element, 2);
82819 if (strpos($pathParts[0], ':') !== false) {
82820 $validURL = null;
82821 } else {
82822 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
82823 }
82824 } else {
82825 $validURL = null;
82826 }
82827 if ($validURL === null) {
82828 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
82829 }
82830 }
82831 break;
82832
82833 case 'email':
82834 $filterFlags = FILTER_NULL_ON_FAILURE;
82835 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
82836
82837 $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
82838 }
82839 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
82840 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
82841 }
82842 break;
82843
82844 case 'ip-address':
82845 case 'ipv4':
82846 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
82847 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
82848 }
82849 break;
82850
82851 case 'ipv6':
82852 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
82853 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
82854 }
82855 break;
82856
82857 case 'host-name':
82858 case 'hostname':
82859 if (!$this->validateHostname($element)) {
82860 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
82861 }
82862 break;
82863
82864 default:
82865
82866
82867
82868
82869
82870
82871 break;
82872 }
82873 }
82874
82875 protected function validateDateTime($datetime, $format)
82876 {
82877 $dt = \DateTime::createFromFormat($format, $datetime);
82878
82879 if (!$dt) {
82880 return false;
82881 }
82882
82883 if ($datetime === $dt->format($format)) {
82884 return true;
82885 }
82886
82887
82888
82889
82890
82891 if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
82892 return true;
82893 }
82894
82895 return false;
82896 }
82897
82898 protected function validateRegex($regex)
82899 {
82900 return false !== @preg_match('/' . $regex . '/u', '');
82901 }
82902
82903 protected function validateColor($color)
82904 {
82905 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
82906 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
82907 'red', 'silver', 'teal', 'white', 'yellow'))) {
82908 return true;
82909 }
82910
82911 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
82912 }
82913
82914 protected function validateStyle($style)
82915 {
82916 $properties = explode(';', rtrim($style, ';'));
82917 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
82918
82919 return empty($invalidEntries);
82920 }
82921
82922 protected function validatePhone($phone)
82923 {
82924 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
82925 }
82926
82927 protected function validateHostname($host)
82928 {
82929 $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';
82930
82931 return preg_match($hostnameRegex, $host);
82932 }
82933 }
82934 <?php
82935
82936
82937
82938
82939
82940
82941
82942
82943 namespace JsonSchema\Constraints;
82944
82945 use JsonSchema\Entity\JsonPointer;
82946
82947
82948
82949
82950
82951
82952
82953 class NumberConstraint extends Constraint
82954 {
82955
82956
82957
82958 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
82959 {
82960
82961 if (isset($schema->exclusiveMinimum)) {
82962 if (isset($schema->minimum)) {
82963 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
82964 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
82965 } elseif ($element < $schema->minimum) {
82966 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
82967 }
82968 } else {
82969 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
82970 }
82971 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
82972 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
82973 }
82974
82975
82976 if (isset($schema->exclusiveMaximum)) {
82977 if (isset($schema->maximum)) {
82978 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
82979 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
82980 } elseif ($element > $schema->maximum) {
82981 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
82982 }
82983 } else {
82984 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
82985 }
82986 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
82987 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
82988 }
82989
82990
82991 if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
82992 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
82993 }
82994
82995
82996 if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
82997 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
82998 }
82999
83000 $this->checkFormat($element, $schema, $path, $i);
83001 }
83002
83003 private function fmod($number1, $number2)
83004 {
83005 $modulus = ($number1 - round($number1 / $number2) * $number2);
83006 $precision = 0.0000000001;
83007
83008 if (-$precision < $modulus && $modulus < $precision) {
83009 return 0.0;
83010 }
83011
83012 return $modulus;
83013 }
83014 }
83015 <?php
83016
83017
83018
83019
83020
83021
83022
83023
83024 namespace JsonSchema\Constraints;
83025
83026 use JsonSchema\Entity\JsonPointer;
83027
83028
83029
83030
83031
83032
83033
83034 class ObjectConstraint extends Constraint
83035 {
83036
83037
83038
83039 protected $appliedDefaults = array();
83040
83041
83042
83043
83044 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
83045 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
83046 {
83047 if ($element instanceof UndefinedConstraint) {
83048 return;
83049 }
83050
83051 $this->appliedDefaults = $appliedDefaults;
83052
83053 $matches = array();
83054 if ($patternProperties) {
83055
83056 $matches = $this->validatePatternProperties($element, $path, $patternProperties);
83057 }
83058
83059 if ($properties) {
83060
83061 $this->validateProperties($element, $properties, $path);
83062 }
83063
83064
83065 $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
83066 }
83067
83068 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
83069 {
83070 $try = array('/', '#', '+', '~', '%');
83071 $matches = array();
83072 foreach ($patternProperties as $pregex => $schema) {
83073 $delimiter = '/';
83074
83075 foreach ($try as $delimiter) {
83076 if (strpos($pregex, $delimiter) === false) { 
83077 break;
83078 }
83079 }
83080
83081
83082 if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
83083 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
83084 continue;
83085 }
83086 foreach ($element as $i => $value) {
83087 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
83088 $matches[] = $i;
83089 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
83090 }
83091 }
83092 }
83093
83094 return $matches;
83095 }
83096
83097
83098
83099
83100
83101
83102
83103
83104
83105
83106
83107 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
83108 $properties = null, $additionalProp = null)
83109 {
83110 $this->validateMinMaxConstraint($element, $schema, $path);
83111
83112 foreach ($element as $i => $value) {
83113 $definition = $this->getProperty($properties, $i);
83114
83115
83116 if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
83117 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
83118 }
83119
83120
83121 if (!in_array($i, $matches) && $additionalProp && !$definition) {
83122 if ($additionalProp === true) {
83123 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
83124 } else {
83125 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
83126 }
83127 }
83128
83129
83130 $require = $this->getProperty($definition, 'requires');
83131 if ($require && !$this->getProperty($element, $require)) {
83132 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
83133 }
83134
83135 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
83136 if (is_object($property)) {
83137 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
83138 }
83139 }
83140 }
83141
83142
83143
83144
83145
83146
83147
83148
83149 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
83150 {
83151 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
83152
83153 foreach ($properties as $i => $value) {
83154 $property = &$this->getProperty($element, $i, $undefinedConstraint);
83155 $definition = $this->getProperty($properties, $i);
83156
83157 if (is_object($definition)) {
83158
83159 $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
83160 }
83161 }
83162 }
83163
83164
83165
83166
83167
83168
83169
83170
83171
83172
83173 protected function &getProperty(&$element, $property, $fallback = null)
83174 {
83175 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
83176 return $element[$property];
83177 } elseif (is_object($element) && property_exists($element, $property)) {
83178 return $element->$property;
83179 }
83180
83181 return $fallback;
83182 }
83183
83184
83185
83186
83187
83188
83189
83190
83191 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
83192 {
83193
83194 if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
83195 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
83196 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
83197 }
83198 }
83199
83200 if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
83201 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
83202 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
83203 }
83204 }
83205 }
83206 }
83207 <?php
83208
83209
83210
83211
83212
83213
83214
83215
83216 namespace JsonSchema\Constraints;
83217
83218 use JsonSchema\Entity\JsonPointer;
83219 use JsonSchema\Exception\InvalidArgumentException;
83220 use JsonSchema\Exception\InvalidSchemaException;
83221 use JsonSchema\Exception\RuntimeException;
83222 use JsonSchema\Validator;
83223
83224
83225
83226
83227
83228
83229
83230 class SchemaConstraint extends Constraint
83231 {
83232 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
83233
83234
83235
83236
83237 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
83238 {
83239 if ($schema !== null) {
83240
83241 $validationSchema = $schema;
83242 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
83243
83244 $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
83245 } else {
83246 throw new InvalidArgumentException('no schema found to verify against');
83247 }
83248
83249
83250 if (is_array($validationSchema)) {
83251 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
83252 }
83253
83254
83255
83256 if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
83257 if (!$this->getTypeCheck()->isObject($validationSchema)) {
83258 throw new RuntimeException('Cannot validate the schema of a non-object');
83259 }
83260 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
83261 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
83262 } else {
83263 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
83264 }
83265
83266
83267 $schemaStorage = $this->factory->getSchemaStorage();
83268 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
83269 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
83270 }
83271
83272
83273 $initialErrorCount = $this->numErrors();
83274 $initialConfig = $this->factory->getConfig();
83275 $initialContext = $this->factory->getErrorContext();
83276 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
83277 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
83278 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
83279
83280
83281 try {
83282 $this->check($validationSchema, $schemaSpec);
83283 } catch (\Exception $e) {
83284 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
83285 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
83286 }
83287 }
83288 if ($this->numErrors() > $initialErrorCount) {
83289 $this->addError($path, 'Schema is not valid', 'schema');
83290 }
83291
83292
83293 $this->factory->setConfig($initialConfig);
83294 $this->factory->setErrorContext($initialContext);
83295 }
83296
83297
83298 $this->checkUndefined($element, $validationSchema, $path, $i);
83299 }
83300 }
83301 <?php
83302
83303
83304
83305
83306
83307
83308
83309
83310 namespace JsonSchema\Constraints;
83311
83312 use JsonSchema\Entity\JsonPointer;
83313
83314
83315
83316
83317
83318
83319
83320 class StringConstraint extends Constraint
83321 {
83322
83323
83324
83325 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
83326 {
83327
83328 if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
83329 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
83330 'maxLength' => $schema->maxLength,
83331 ));
83332 }
83333
83334
83335 if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
83336 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
83337 'minLength' => $schema->minLength,
83338 ));
83339 }
83340
83341
83342 if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
83343 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
83344 'pattern' => $schema->pattern,
83345 ));
83346 }
83347
83348 $this->checkFormat($element, $schema, $path, $i);
83349 }
83350
83351 private function strlen($string)
83352 {
83353 if (extension_loaded('mbstring')) {
83354 return mb_strlen($string, mb_detect_encoding($string));
83355 }
83356
83357
83358 return strlen($string); 
83359 }
83360 }
83361 <?php
83362
83363 namespace JsonSchema\Constraints\TypeCheck;
83364
83365 class LooseTypeCheck implements TypeCheckInterface
83366 {
83367 public static function isObject($value)
83368 {
83369 return
83370 is_object($value) ||
83371 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
83372 }
83373
83374 public static function isArray($value)
83375 {
83376 return
83377 is_array($value) &&
83378 (count($value) == 0 || !self::isAssociativeArray($value));
83379 }
83380
83381 public static function propertyGet($value, $property)
83382 {
83383 if (is_object($value)) {
83384 return $value->{$property};
83385 }
83386
83387 return $value[$property];
83388 }
83389
83390 public static function propertySet(&$value, $property, $data)
83391 {
83392 if (is_object($value)) {
83393 $value->{$property} = $data;
83394 } else {
83395 $value[$property] = $data;
83396 }
83397 }
83398
83399 public static function propertyExists($value, $property)
83400 {
83401 if (is_object($value)) {
83402 return property_exists($value, $property);
83403 }
83404
83405 return array_key_exists($property, $value);
83406 }
83407
83408 public static function propertyCount($value)
83409 {
83410 if (is_object($value)) {
83411 return count(get_object_vars($value));
83412 }
83413
83414 return count($value);
83415 }
83416
83417
83418
83419
83420
83421
83422
83423
83424 private static function isAssociativeArray($arr)
83425 {
83426 return array_keys($arr) !== range(0, count($arr) - 1);
83427 }
83428 }
83429 <?php
83430
83431 namespace JsonSchema\Constraints\TypeCheck;
83432
83433 class StrictTypeCheck implements TypeCheckInterface
83434 {
83435 public static function isObject($value)
83436 {
83437 return is_object($value);
83438 }
83439
83440 public static function isArray($value)
83441 {
83442 return is_array($value);
83443 }
83444
83445 public static function propertyGet($value, $property)
83446 {
83447 return $value->{$property};
83448 }
83449
83450 public static function propertySet(&$value, $property, $data)
83451 {
83452 $value->{$property} = $data;
83453 }
83454
83455 public static function propertyExists($value, $property)
83456 {
83457 return property_exists($value, $property);
83458 }
83459
83460 public static function propertyCount($value)
83461 {
83462 if (!is_object($value)) {
83463 return 0;
83464 }
83465
83466 return count(get_object_vars($value));
83467 }
83468 }
83469 <?php
83470
83471 namespace JsonSchema\Constraints\TypeCheck;
83472
83473 interface TypeCheckInterface
83474 {
83475 public static function isObject($value);
83476
83477 public static function isArray($value);
83478
83479 public static function propertyGet($value, $property);
83480
83481 public static function propertySet(&$value, $property, $data);
83482
83483 public static function propertyExists($value, $property);
83484
83485 public static function propertyCount($value);
83486 }
83487 <?php
83488
83489
83490
83491
83492
83493
83494
83495
83496 namespace JsonSchema\Constraints;
83497
83498 use JsonSchema\Entity\JsonPointer;
83499 use JsonSchema\Exception\InvalidArgumentException;
83500 use UnexpectedValueException as StandardUnexpectedValueException;
83501
83502
83503
83504
83505
83506
83507
83508 class TypeConstraint extends Constraint
83509 {
83510
83511
83512
83513 public static $wording = array(
83514 'integer' => 'an integer',
83515 'number' => 'a number',
83516 'boolean' => 'a boolean',
83517 'object' => 'an object',
83518 'array' => 'an array',
83519 'string' => 'a string',
83520 'null' => 'a null',
83521 'any' => null, 
83522 0 => null, 
83523 );
83524
83525
83526
83527
83528 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
83529 {
83530 $type = isset($schema->type) ? $schema->type : null;
83531 $isValid = false;
83532 $wording = array();
83533
83534 if (is_array($type)) {
83535 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
83536 } elseif (is_object($type)) {
83537 $this->checkUndefined($value, $type, $path);
83538
83539 return;
83540 } else {
83541 $isValid = $this->validateType($value, $type);
83542 }
83543
83544 if ($isValid === false) {
83545 if (!is_array($type)) {
83546 $this->validateTypeNameWording($type);
83547 $wording[] = self::$wording[$type];
83548 }
83549 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
83550 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
83551 }
83552 }
83553
83554
83555
83556
83557
83558
83559
83560
83561
83562
83563
83564
83565 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
83566 {
83567 foreach ($type as $tp) {
83568
83569
83570 if (is_object($tp)) {
83571 if (!$isValid) {
83572 $validator = $this->factory->createInstanceFor('type');
83573 $subSchema = new \stdClass();
83574 $subSchema->type = $tp;
83575 $validator->check($value, $subSchema, $path, null);
83576 $error = $validator->getErrors();
83577 $isValid = !(bool) $error;
83578 $validTypesWording[] = self::$wording['object'];
83579 }
83580 } else {
83581 $this->validateTypeNameWording($tp);
83582 $validTypesWording[] = self::$wording[$tp];
83583 if (!$isValid) {
83584 $isValid = $this->validateType($value, $tp);
83585 }
83586 }
83587 }
83588 }
83589
83590
83591
83592
83593
83594
83595
83596
83597
83598
83599
83600
83601 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
83602 {
83603 if ($listEnd === false || !isset($elements[1])) {
83604 return implode($delimiter, $elements);
83605 }
83606 $lastElement = array_slice($elements, -1);
83607 $firsElements = join($delimiter, array_slice($elements, 0, -1));
83608 $implodedElements = array_merge(array($firsElements), $lastElement);
83609
83610 return join(" $listEnd ", $implodedElements);
83611 }
83612
83613
83614
83615
83616
83617
83618
83619
83620
83621 protected function validateTypeNameWording($type)
83622 {
83623 if (!isset(self::$wording[$type])) {
83624 throw new StandardUnexpectedValueException(
83625 sprintf(
83626 'No wording for %s available, expected wordings are: [%s]',
83627 var_export($type, true),
83628 implode(', ', array_filter(self::$wording)))
83629 );
83630 }
83631 }
83632
83633
83634
83635
83636
83637
83638
83639
83640
83641
83642
83643 protected function validateType(&$value, $type)
83644 {
83645
83646 if (!$type) {
83647 return true;
83648 }
83649
83650 if ('any' === $type) {
83651 return true;
83652 }
83653
83654 if ('object' === $type) {
83655 return $this->getTypeCheck()->isObject($value);
83656 }
83657
83658 if ('array' === $type) {
83659 return $this->getTypeCheck()->isArray($value);
83660 }
83661
83662 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
83663
83664 if ('integer' === $type) {
83665 if ($coerce) {
83666 $value = $this->toInteger($value);
83667 }
83668
83669 return is_int($value);
83670 }
83671
83672 if ('number' === $type) {
83673 if ($coerce) {
83674 $value = $this->toNumber($value);
83675 }
83676
83677 return is_numeric($value) && !is_string($value);
83678 }
83679
83680 if ('boolean' === $type) {
83681 if ($coerce) {
83682 $value = $this->toBoolean($value);
83683 }
83684
83685 return is_bool($value);
83686 }
83687
83688 if ('string' === $type) {
83689 return is_string($value);
83690 }
83691
83692 if ('email' === $type) {
83693 return is_string($value);
83694 }
83695
83696 if ('null' === $type) {
83697 return is_null($value);
83698 }
83699
83700 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
83701 }
83702
83703
83704
83705
83706
83707
83708
83709
83710 protected function toBoolean($value)
83711 {
83712 if ($value === 'true') {
83713 return true;
83714 }
83715
83716 if ($value === 'false') {
83717 return false;
83718 }
83719
83720 return $value;
83721 }
83722
83723
83724
83725
83726
83727
83728
83729
83730 protected function toNumber($value)
83731 {
83732 if (is_numeric($value)) {
83733 return $value + 0; 
83734 }
83735
83736 return $value;
83737 }
83738
83739 protected function toInteger($value)
83740 {
83741 if (is_numeric($value) && (int) $value == $value) {
83742 return (int) $value; 
83743 }
83744
83745 return $value;
83746 }
83747 }
83748 <?php
83749
83750
83751
83752
83753
83754
83755
83756
83757 namespace JsonSchema\Constraints;
83758
83759 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
83760 use JsonSchema\Entity\JsonPointer;
83761 use JsonSchema\Exception\ValidationException;
83762 use JsonSchema\Uri\UriResolver;
83763
83764
83765
83766
83767
83768
83769
83770 class UndefinedConstraint extends Constraint
83771 {
83772
83773
83774
83775 protected $appliedDefaults = array();
83776
83777
83778
83779
83780 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
83781 {
83782 if (is_null($schema) || !is_object($schema)) {
83783 return;
83784 }
83785
83786 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
83787 if ($fromDefault) {
83788 $path->setFromDefault();
83789 }
83790
83791
83792 $this->validateCommonProperties($value, $schema, $path, $i);
83793
83794
83795 $this->validateOfProperties($value, $schema, $path, '');
83796
83797
83798 $this->validateTypes($value, $schema, $path, $i);
83799 }
83800
83801
83802
83803
83804
83805
83806
83807
83808
83809 public function validateTypes(&$value, $schema, JsonPointer $path, $i = null)
83810 {
83811
83812 if ($this->getTypeCheck()->isArray($value)) {
83813 $this->checkArray($value, $schema, $path, $i);
83814 }
83815
83816
83817 if (LooseTypeCheck::isObject($value)) { 
83818
83819
83820 $this->checkObject(
83821 $value,
83822 $schema,
83823 $path,
83824 isset($schema->properties) ? $schema->properties : null,
83825 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
83826 isset($schema->patternProperties) ? $schema->patternProperties : null,
83827 $this->appliedDefaults
83828 );
83829 }
83830
83831
83832 if (is_string($value)) {
83833 $this->checkString($value, $schema, $path, $i);
83834 }
83835
83836
83837 if (is_numeric($value)) {
83838 $this->checkNumber($value, $schema, $path, $i);
83839 }
83840
83841
83842 if (isset($schema->enum)) {
83843 $this->checkEnum($value, $schema, $path, $i);
83844 }
83845 }
83846
83847
83848
83849
83850
83851
83852
83853
83854
83855 protected function validateCommonProperties(&$value, $schema, JsonPointer $path, $i = '')
83856 {
83857
83858 if (isset($schema->extends)) {
83859 if (is_string($schema->extends)) {
83860 $schema->extends = $this->validateUri($schema, $schema->extends);
83861 }
83862 if (is_array($schema->extends)) {
83863 foreach ($schema->extends as $extends) {
83864 $this->checkUndefined($value, $extends, $path, $i);
83865 }
83866 } else {
83867 $this->checkUndefined($value, $schema->extends, $path, $i);
83868 }
83869 }
83870
83871
83872 if (!$path->fromDefault()) {
83873 $this->applyDefaultValues($value, $schema, $path);
83874 }
83875
83876
83877 if ($this->getTypeCheck()->isObject($value)) {
83878 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
83879
83880 foreach ($schema->required as $required) {
83881 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
83882 $this->addError(
83883 $this->incrementPath($path ?: new JsonPointer(''), $required),
83884 'The property ' . $required . ' is required',
83885 'required'
83886 );
83887 }
83888 }
83889 } elseif (isset($schema->required) && !is_array($schema->required)) {
83890
83891 if ($schema->required && $value instanceof self) {
83892 $propertyPaths = $path->getPropertyPaths();
83893 $propertyName = end($propertyPaths);
83894 $this->addError(
83895 $path,
83896 'The property ' . $propertyName . ' is required',
83897 'required'
83898 );
83899 }
83900 } else {
83901
83902
83903 if ($value instanceof self) {
83904 return;
83905 }
83906 }
83907 }
83908
83909
83910 if (!($value instanceof self)) {
83911 $this->checkType($value, $schema, $path, $i);
83912 }
83913
83914
83915 if (isset($schema->disallow)) {
83916 $initErrors = $this->getErrors();
83917
83918 $typeSchema = new \stdClass();
83919 $typeSchema->type = $schema->disallow;
83920 $this->checkType($value, $typeSchema, $path);
83921
83922
83923 if (count($this->getErrors()) == count($initErrors)) {
83924 $this->addError($path, 'Disallowed value was matched', 'disallow');
83925 } else {
83926 $this->errors = $initErrors;
83927 }
83928 }
83929
83930 if (isset($schema->not)) {
83931 $initErrors = $this->getErrors();
83932 $this->checkUndefined($value, $schema->not, $path, $i);
83933
83934
83935 if (count($this->getErrors()) == count($initErrors)) {
83936 $this->addError($path, 'Matched a schema which it should not', 'not');
83937 } else {
83938 $this->errors = $initErrors;
83939 }
83940 }
83941
83942
83943 if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
83944 $this->validateDependencies($value, $schema->dependencies, $path);
83945 }
83946 }
83947
83948
83949
83950
83951
83952
83953
83954
83955
83956
83957 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
83958 {
83959
83960 if (!$requiredOnly) {
83961 return true;
83962 }
83963
83964 if (
83965 $name !== null
83966 && isset($parentSchema->required)
83967 && is_array($parentSchema->required)
83968 && in_array($name, $parentSchema->required)
83969 ) {
83970 return true;
83971 }
83972
83973 if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
83974 return true;
83975 }
83976
83977 return false;
83978 }
83979
83980
83981
83982
83983
83984
83985
83986
83987 protected function applyDefaultValues(&$value, $schema, $path)
83988 {
83989
83990 if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
83991 return;
83992 }
83993
83994
83995 $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
83996 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
83997
83998 foreach ($schema->properties as $currentProperty => $propertyDefinition) {
83999 $propertyDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($propertyDefinition);
84000 if (
84001 !LooseTypeCheck::propertyExists($value, $currentProperty)
84002 && property_exists($propertyDefinition, 'default')
84003 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
84004 ) {
84005
84006 if (is_object($propertyDefinition->default)) {
84007 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
84008 } else {
84009 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
84010 }
84011 $this->appliedDefaults[] = $currentProperty;
84012 }
84013 }
84014 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
84015 $items = array();
84016 if (LooseTypeCheck::isArray($schema->items)) {
84017 $items = $schema->items;
84018 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
84019 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
84020 }
84021
84022 foreach ($items as $currentItem => $itemDefinition) {
84023 $itemDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($itemDefinition);
84024 if (
84025 !array_key_exists($currentItem, $value)
84026 && property_exists($itemDefinition, 'default')
84027 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
84028 if (is_object($itemDefinition->default)) {
84029 $value[$currentItem] = clone $itemDefinition->default;
84030 } else {
84031 $value[$currentItem] = $itemDefinition->default;
84032 }
84033 }
84034 $path->setFromDefault();
84035 }
84036 } elseif (
84037 $value instanceof self
84038 && property_exists($schema, 'default')
84039 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
84040
84041 $value = is_object($schema->default) ? clone $schema->default : $schema->default;
84042 $path->setFromDefault();
84043 }
84044 }
84045
84046
84047
84048
84049
84050
84051
84052
84053
84054 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
84055 {
84056
84057 if ($value instanceof self) {
84058 return;
84059 }
84060
84061 if (isset($schema->allOf)) {
84062 $isValid = true;
84063 foreach ($schema->allOf as $allOf) {
84064 $initErrors = $this->getErrors();
84065 $this->checkUndefined($value, $allOf, $path, $i);
84066 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
84067 }
84068 if (!$isValid) {
84069 $this->addError($path, 'Failed to match all schemas', 'allOf');
84070 }
84071 }
84072
84073 if (isset($schema->anyOf)) {
84074 $isValid = false;
84075 $startErrors = $this->getErrors();
84076 $caughtException = null;
84077 foreach ($schema->anyOf as $anyOf) {
84078 $initErrors = $this->getErrors();
84079 try {
84080 $this->checkUndefined($value, $anyOf, $path, $i);
84081 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
84082 break;
84083 }
84084 } catch (ValidationException $e) {
84085 $isValid = false;
84086 }
84087 }
84088 if (!$isValid) {
84089 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
84090 } else {
84091 $this->errors = $startErrors;
84092 }
84093 }
84094
84095 if (isset($schema->oneOf)) {
84096 $allErrors = array();
84097 $matchedSchemas = 0;
84098 $startErrors = $this->getErrors();
84099 foreach ($schema->oneOf as $oneOf) {
84100 try {
84101 $this->errors = array();
84102 $this->checkUndefined($value, $oneOf, $path, $i);
84103 if (count($this->getErrors()) == 0) {
84104 $matchedSchemas++;
84105 }
84106 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
84107 } catch (ValidationException $e) {
84108
84109
84110 }
84111 }
84112 if ($matchedSchemas !== 1) {
84113 $this->addErrors(array_merge($allErrors, $startErrors));
84114 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
84115 } else {
84116 $this->errors = $startErrors;
84117 }
84118 }
84119 }
84120
84121
84122
84123
84124
84125
84126
84127
84128
84129 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
84130 {
84131 foreach ($dependencies as $key => $dependency) {
84132 if ($this->getTypeCheck()->propertyExists($value, $key)) {
84133 if (is_string($dependency)) {
84134
84135 if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
84136 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
84137 }
84138 } elseif (is_array($dependency)) {
84139
84140 foreach ($dependency as $d) {
84141 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
84142 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
84143 }
84144 }
84145 } elseif (is_object($dependency)) {
84146
84147 $this->checkUndefined($value, $dependency, $path, $i);
84148 }
84149 }
84150 }
84151 }
84152
84153 protected function validateUri($schema, $schemaUri = null)
84154 {
84155 $resolver = new UriResolver();
84156 $retriever = $this->factory->getUriRetriever();
84157
84158 $jsonSchema = null;
84159 if ($resolver->isValid($schemaUri)) {
84160 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
84161 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
84162 }
84163
84164 return $jsonSchema;
84165 }
84166 }
84167 <?php
84168
84169
84170
84171
84172
84173
84174
84175
84176 namespace JsonSchema\Entity;
84177
84178 use JsonSchema\Exception\InvalidArgumentException;
84179
84180
84181
84182
84183
84184
84185 class JsonPointer
84186 {
84187
84188 private $filename;
84189
84190
84191 private $propertyPaths = array();
84192
84193
84194
84195
84196 private $fromDefault = false;
84197
84198
84199
84200
84201
84202
84203 public function __construct($value)
84204 {
84205 if (!is_string($value)) {
84206 throw new InvalidArgumentException('Ref value must be a string');
84207 }
84208
84209 $splitRef = explode('#', $value, 2);
84210 $this->filename = $splitRef[0];
84211 if (array_key_exists(1, $splitRef)) {
84212 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
84213 }
84214 }
84215
84216
84217
84218
84219
84220
84221 private function decodePropertyPaths($propertyPathString)
84222 {
84223 $paths = array();
84224 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
84225 $path = $this->decodePath($path);
84226 if (is_string($path) && '' !== $path) {
84227 $paths[] = $path;
84228 }
84229 }
84230
84231 return $paths;
84232 }
84233
84234
84235
84236
84237 private function encodePropertyPaths()
84238 {
84239 return array_map(
84240 array($this, 'encodePath'),
84241 $this->getPropertyPaths()
84242 );
84243 }
84244
84245
84246
84247
84248
84249
84250 private function decodePath($path)
84251 {
84252 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
84253 }
84254
84255
84256
84257
84258
84259
84260 private function encodePath($path)
84261 {
84262 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
84263 }
84264
84265
84266
84267
84268 public function getFilename()
84269 {
84270 return $this->filename;
84271 }
84272
84273
84274
84275
84276 public function getPropertyPaths()
84277 {
84278 return $this->propertyPaths;
84279 }
84280
84281
84282
84283
84284
84285
84286 public function withPropertyPaths(array $propertyPaths)
84287 {
84288 $new = clone $this;
84289 $new->propertyPaths = $propertyPaths;
84290
84291 return $new;
84292 }
84293
84294
84295
84296
84297 public function getPropertyPathAsString()
84298 {
84299 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
84300 }
84301
84302
84303
84304
84305 public function __toString()
84306 {
84307 return $this->getFilename() . $this->getPropertyPathAsString();
84308 }
84309
84310
84311
84312
84313 public function setFromDefault()
84314 {
84315 $this->fromDefault = true;
84316 }
84317
84318
84319
84320
84321
84322
84323 public function fromDefault()
84324 {
84325 return $this->fromDefault;
84326 }
84327 }
84328 <?php
84329
84330 namespace JsonSchema\Exception;
84331
84332 interface ExceptionInterface
84333 {
84334 }
84335 <?php
84336
84337
84338
84339
84340
84341
84342
84343
84344 namespace JsonSchema\Exception;
84345
84346
84347
84348
84349 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
84350 {
84351 }
84352 <?php
84353
84354
84355
84356
84357
84358
84359
84360
84361 namespace JsonSchema\Exception;
84362
84363
84364
84365
84366 class InvalidConfigException extends RuntimeException
84367 {
84368 }
84369 <?php
84370
84371
84372
84373
84374
84375
84376
84377
84378 namespace JsonSchema\Exception;
84379
84380
84381
84382
84383 class InvalidSchemaException extends RuntimeException
84384 {
84385 }
84386 <?php
84387
84388
84389
84390
84391
84392
84393
84394
84395 namespace JsonSchema\Exception;
84396
84397
84398
84399
84400 class InvalidSchemaMediaTypeException extends RuntimeException
84401 {
84402 }
84403 <?php
84404
84405
84406
84407
84408
84409
84410
84411
84412 namespace JsonSchema\Exception;
84413
84414
84415
84416
84417 class InvalidSourceUriException extends InvalidArgumentException
84418 {
84419 }
84420 <?php
84421
84422
84423
84424
84425
84426
84427
84428
84429 namespace JsonSchema\Exception;
84430
84431
84432
84433
84434 class JsonDecodingException extends RuntimeException
84435 {
84436 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
84437 {
84438 switch ($code) {
84439 case JSON_ERROR_DEPTH:
84440 $message = 'The maximum stack depth has been exceeded';
84441 break;
84442 case JSON_ERROR_STATE_MISMATCH:
84443 $message = 'Invalid or malformed JSON';
84444 break;
84445 case JSON_ERROR_CTRL_CHAR:
84446 $message = 'Control character error, possibly incorrectly encoded';
84447 break;
84448 case JSON_ERROR_UTF8:
84449 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
84450 break;
84451 case JSON_ERROR_SYNTAX:
84452 $message = 'JSON syntax is malformed';
84453 break;
84454 default:
84455 $message = 'Syntax error';
84456 }
84457 parent::__construct($message, $code, $previous);
84458 }
84459 }
84460 <?php
84461
84462
84463
84464
84465
84466
84467
84468
84469 namespace JsonSchema\Exception;
84470
84471
84472
84473
84474 class ResourceNotFoundException extends RuntimeException
84475 {
84476 }
84477 <?php
84478
84479
84480
84481
84482
84483
84484
84485
84486 namespace JsonSchema\Exception;
84487
84488
84489
84490
84491 class RuntimeException extends \RuntimeException implements ExceptionInterface
84492 {
84493 }
84494 <?php
84495
84496
84497
84498
84499
84500
84501
84502
84503 namespace JsonSchema\Exception;
84504
84505
84506
84507
84508
84509
84510 class UnresolvableJsonPointerException extends InvalidArgumentException
84511 {
84512 }
84513 <?php
84514
84515
84516
84517
84518
84519
84520
84521
84522 namespace JsonSchema\Exception;
84523
84524
84525
84526
84527 class UriResolverException extends RuntimeException
84528 {
84529 }
84530 <?php
84531
84532
84533
84534
84535
84536
84537
84538
84539 namespace JsonSchema\Exception;
84540
84541 class ValidationException extends RuntimeException
84542 {
84543 }
84544 <?php
84545
84546
84547
84548
84549
84550
84551
84552
84553 namespace JsonSchema\Iterator;
84554
84555
84556
84557
84558
84559
84560 class ObjectIterator implements \Iterator, \Countable
84561 {
84562
84563 private $object;
84564
84565
84566 private $position = 0;
84567
84568
84569 private $data = array();
84570
84571
84572 private $initialized = false;
84573
84574
84575
84576
84577 public function __construct($object)
84578 {
84579 $this->object = $object;
84580 }
84581
84582
84583
84584
84585 public function current()
84586 {
84587 $this->initialize();
84588
84589 return $this->data[$this->position];
84590 }
84591
84592
84593
84594
84595 public function next()
84596 {
84597 $this->initialize();
84598 $this->position++;
84599 }
84600
84601
84602
84603
84604 public function key()
84605 {
84606 $this->initialize();
84607
84608 return $this->position;
84609 }
84610
84611
84612
84613
84614 public function valid()
84615 {
84616 $this->initialize();
84617
84618 return isset($this->data[$this->position]);
84619 }
84620
84621
84622
84623
84624 public function rewind()
84625 {
84626 $this->initialize();
84627 $this->position = 0;
84628 }
84629
84630
84631
84632
84633 public function count()
84634 {
84635 $this->initialize();
84636
84637 return count($this->data);
84638 }
84639
84640
84641
84642
84643 private function initialize()
84644 {
84645 if (!$this->initialized) {
84646 $this->data = $this->buildDataFromObject($this->object);
84647 $this->initialized = true;
84648 }
84649 }
84650
84651
84652
84653
84654
84655
84656 private function buildDataFromObject($object)
84657 {
84658 $result = array();
84659
84660 $stack = new \SplStack();
84661 $stack->push($object);
84662
84663 while (!$stack->isEmpty()) {
84664 $current = $stack->pop();
84665 if (is_object($current)) {
84666 array_push($result, $current);
84667 }
84668
84669 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
84670 if (is_object($propertyValue) || is_array($propertyValue)) {
84671 $stack->push($propertyValue);
84672 }
84673 }
84674 }
84675
84676 return $result;
84677 }
84678
84679
84680
84681
84682
84683
84684 private function getDataFromItem($item)
84685 {
84686 if (!is_object($item) && !is_array($item)) {
84687 return array();
84688 }
84689
84690 return is_object($item) ? get_object_vars($item) : $item;
84691 }
84692 }
84693 <?php
84694
84695 namespace JsonSchema;
84696
84697 class Rfc3339
84698 {
84699 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
84700
84701
84702
84703
84704
84705
84706
84707
84708 public static function createFromString($string)
84709 {
84710 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
84711 return null;
84712 }
84713
84714 $dateAndTime = $matches[1];
84715 $microseconds = $matches[2] ?: '.000000';
84716 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
84717 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
84718 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
84719
84720 return $dateTime ?: null;
84721 }
84722 }
84723 <?php
84724
84725 namespace JsonSchema;
84726
84727 use JsonSchema\Constraints\BaseConstraint;
84728 use JsonSchema\Entity\JsonPointer;
84729 use JsonSchema\Exception\UnresolvableJsonPointerException;
84730 use JsonSchema\Uri\UriResolver;
84731 use JsonSchema\Uri\UriRetriever;
84732
84733 class SchemaStorage implements SchemaStorageInterface
84734 {
84735 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
84736
84737 protected $uriRetriever;
84738 protected $uriResolver;
84739 protected $schemas = array();
84740
84741 public function __construct(
84742 UriRetrieverInterface $uriRetriever = null,
84743 UriResolverInterface $uriResolver = null
84744 ) {
84745 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
84746 $this->uriResolver = $uriResolver ?: new UriResolver();
84747 }
84748
84749
84750
84751
84752 public function getUriRetriever()
84753 {
84754 return $this->uriRetriever;
84755 }
84756
84757
84758
84759
84760 public function getUriResolver()
84761 {
84762 return $this->uriResolver;
84763 }
84764
84765
84766
84767
84768 public function addSchema($id, $schema = null)
84769 {
84770 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
84771
84772
84773
84774 $schema = $this->uriRetriever->retrieve($id);
84775 }
84776
84777
84778 if (is_array($schema)) {
84779 $schema = BaseConstraint::arrayToObjectRecursive($schema);
84780 }
84781
84782
84783
84784 if (is_object($schema) && property_exists($schema, 'id')) {
84785 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
84786 $schema->properties->id->format = 'uri-reference';
84787 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
84788 $schema->properties->id->format = 'uri-reference';
84789 $schema->properties->{'$ref'}->format = 'uri-reference';
84790 }
84791 }
84792
84793
84794 $this->expandRefs($schema, $id);
84795
84796 $this->schemas[$id] = $schema;
84797 }
84798
84799
84800
84801
84802
84803
84804
84805 private function expandRefs(&$schema, $base = null)
84806 {
84807 if (!is_object($schema)) {
84808 if (is_array($schema)) {
84809 foreach ($schema as &$member) {
84810 $this->expandRefs($member, $base);
84811 }
84812 }
84813
84814 return;
84815 }
84816
84817 if (property_exists($schema, 'id') && is_string($schema->id) && $base != $schema->id) {
84818 $base = $this->uriResolver->resolve($schema->id, $base);
84819 }
84820
84821 if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
84822 $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $base));
84823 $schema->{'$ref'} = (string) $refPointer;
84824 }
84825
84826 foreach ($schema as &$member) {
84827 $this->expandRefs($member, $base);
84828 }
84829 }
84830
84831
84832
84833
84834 public function getSchema($id)
84835 {
84836 if (!array_key_exists($id, $this->schemas)) {
84837 $this->addSchema($id);
84838 }
84839
84840 return $this->schemas[$id];
84841 }
84842
84843
84844
84845
84846 public function resolveRef($ref)
84847 {
84848 $jsonPointer = new JsonPointer($ref);
84849
84850
84851 $fileName = $jsonPointer->getFilename();
84852 if (!strlen($fileName)) {
84853 throw new UnresolvableJsonPointerException(sprintf(
84854 "Could not resolve fragment '%s': no file is defined",
84855 $jsonPointer->getPropertyPathAsString()
84856 ));
84857 }
84858
84859
84860 $refSchema = $this->getSchema($fileName);
84861 foreach ($jsonPointer->getPropertyPaths() as $path) {
84862 if (is_object($refSchema) && property_exists($refSchema, $path)) {
84863 $refSchema = $this->resolveRefSchema($refSchema->{$path});
84864 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
84865 $refSchema = $this->resolveRefSchema($refSchema[$path]);
84866 } else {
84867 throw new UnresolvableJsonPointerException(sprintf(
84868 'File: %s is found, but could not resolve fragment: %s',
84869 $jsonPointer->getFilename(),
84870 $jsonPointer->getPropertyPathAsString()
84871 ));
84872 }
84873 }
84874
84875 return $refSchema;
84876 }
84877
84878
84879
84880
84881 public function resolveRefSchema($refSchema)
84882 {
84883 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
84884 $newSchema = $this->resolveRef($refSchema->{'$ref'});
84885 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
84886 unset($refSchema->{'$ref'});
84887 }
84888
84889 return $refSchema;
84890 }
84891 }
84892 <?php
84893
84894 namespace JsonSchema;
84895
84896 interface SchemaStorageInterface
84897 {
84898
84899
84900
84901
84902
84903
84904 public function addSchema($id, $schema = null);
84905
84906
84907
84908
84909
84910
84911
84912
84913 public function getSchema($id);
84914
84915
84916
84917
84918
84919
84920
84921
84922 public function resolveRef($ref);
84923
84924
84925
84926
84927
84928
84929
84930
84931 public function resolveRefSchema($refSchema);
84932 }
84933 <?php
84934
84935
84936
84937
84938
84939
84940 namespace JsonSchema\Uri\Retrievers;
84941
84942
84943
84944
84945
84946
84947
84948 abstract class AbstractRetriever implements UriRetrieverInterface
84949 {
84950
84951
84952
84953
84954
84955 protected $contentType;
84956
84957
84958
84959
84960
84961
84962 public function getContentType()
84963 {
84964 return $this->contentType;
84965 }
84966 }
84967 <?php
84968
84969
84970
84971
84972
84973
84974
84975
84976 namespace JsonSchema\Uri\Retrievers;
84977
84978 use JsonSchema\Exception\RuntimeException;
84979 use JsonSchema\Validator;
84980
84981
84982
84983
84984
84985
84986 class Curl extends AbstractRetriever
84987 {
84988 protected $messageBody;
84989
84990 public function __construct()
84991 {
84992 if (!function_exists('curl_init')) {
84993
84994 throw new RuntimeException('cURL not installed'); 
84995 }
84996 }
84997
84998
84999
85000
85001
85002
85003 public function retrieve($uri)
85004 {
85005 $ch = curl_init();
85006
85007 curl_setopt($ch, CURLOPT_URL, $uri);
85008 curl_setopt($ch, CURLOPT_HEADER, true);
85009 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
85010 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
85011
85012 $response = curl_exec($ch);
85013 if (false === $response) {
85014 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
85015 }
85016
85017 $this->fetchMessageBody($response);
85018 $this->fetchContentType($response);
85019
85020 curl_close($ch);
85021
85022 return $this->messageBody;
85023 }
85024
85025
85026
85027
85028 private function fetchMessageBody($response)
85029 {
85030 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
85031 $this->messageBody = $match[1];
85032 }
85033
85034
85035
85036
85037
85038
85039 protected function fetchContentType($response)
85040 {
85041 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
85042 $this->contentType = trim($match[1]);
85043
85044 return true;
85045 }
85046
85047 return false;
85048 }
85049 }
85050 <?php
85051
85052
85053
85054
85055
85056
85057
85058
85059 namespace JsonSchema\Uri\Retrievers;
85060
85061 use JsonSchema\Exception\ResourceNotFoundException;
85062
85063
85064
85065
85066
85067
85068 class FileGetContents extends AbstractRetriever
85069 {
85070 protected $messageBody;
85071
85072
85073
85074
85075
85076
85077 public function retrieve($uri)
85078 {
85079 $errorMessage = null;
85080 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
85081 $errorMessage = $errstr;
85082 });
85083 $response = file_get_contents($uri);
85084 restore_error_handler();
85085
85086 if ($errorMessage) {
85087 throw new ResourceNotFoundException($errorMessage);
85088 }
85089
85090 if (false === $response) {
85091 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
85092 }
85093
85094 if ($response == ''
85095 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
85096 ) {
85097 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
85098 }
85099
85100 $this->messageBody = $response;
85101 if (!empty($http_response_header)) {
85102
85103
85104 $this->fetchContentType($http_response_header); 
85105 } else { 
85106
85107 $this->contentType = null;
85108 }
85109
85110 return $this->messageBody;
85111 }
85112
85113
85114
85115
85116
85117
85118 private function fetchContentType(array $headers)
85119 {
85120 foreach ($headers as $header) {
85121 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
85122 return true;
85123 }
85124 }
85125
85126 return false;
85127 }
85128
85129
85130
85131
85132
85133
85134 protected static function getContentTypeMatchInHeader($header)
85135 {
85136 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
85137 return trim($match[1]);
85138 }
85139
85140 return null;
85141 }
85142 }
85143 <?php
85144
85145 namespace JsonSchema\Uri\Retrievers;
85146
85147 use JsonSchema\Validator;
85148
85149
85150
85151
85152
85153
85154
85155
85156
85157
85158
85159
85160
85161 class PredefinedArray extends AbstractRetriever
85162 {
85163
85164
85165
85166
85167
85168 private $schemas;
85169
85170
85171
85172
85173
85174
85175
85176 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
85177 {
85178 $this->schemas = $schemas;
85179 $this->contentType = $contentType;
85180 }
85181
85182
85183
85184
85185
85186
85187 public function retrieve($uri)
85188 {
85189 if (!array_key_exists($uri, $this->schemas)) {
85190 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
85191 'The JSON schema "%s" was not found.',
85192 $uri
85193 ));
85194 }
85195
85196 return $this->schemas[$uri];
85197 }
85198 }
85199 <?php
85200
85201
85202
85203
85204
85205
85206
85207
85208 namespace JsonSchema\Uri\Retrievers;
85209
85210
85211
85212
85213
85214
85215 interface UriRetrieverInterface
85216 {
85217
85218
85219
85220
85221
85222
85223
85224
85225
85226 public function retrieve($uri);
85227
85228
85229
85230
85231
85232
85233 public function getContentType();
85234 }
85235 <?php
85236
85237
85238
85239
85240
85241
85242
85243
85244 namespace JsonSchema\Uri;
85245
85246 use JsonSchema\Exception\UriResolverException;
85247 use JsonSchema\UriResolverInterface;
85248
85249
85250
85251
85252
85253
85254 class UriResolver implements UriResolverInterface
85255 {
85256
85257
85258
85259
85260
85261
85262
85263 public function parse($uri)
85264 {
85265 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
85266
85267 $components = array();
85268 if (5 < count($match)) {
85269 $components = array(
85270 'scheme' => $match[2],
85271 'authority' => $match[4],
85272 'path' => $match[5]
85273 );
85274 }
85275 if (7 < count($match)) {
85276 $components['query'] = $match[7];
85277 }
85278 if (9 < count($match)) {
85279 $components['fragment'] = $match[9];
85280 }
85281
85282 return $components;
85283 }
85284
85285
85286
85287
85288
85289
85290
85291
85292 public function generate(array $components)
85293 {
85294 $uri = $components['scheme'] . '://'
85295 . $components['authority']
85296 . $components['path'];
85297
85298 if (array_key_exists('query', $components) && strlen($components['query'])) {
85299 $uri .= '?' . $components['query'];
85300 }
85301 if (array_key_exists('fragment', $components)) {
85302 $uri .= '#' . $components['fragment'];
85303 }
85304
85305 return $uri;
85306 }
85307
85308
85309
85310
85311 public function resolve($uri, $baseUri = null)
85312 {
85313
85314 if (
85315 !is_null($baseUri) &&
85316 !filter_var($baseUri, \FILTER_VALIDATE_URL) &&
85317 !preg_match('|^[^/]+://|u', $baseUri)
85318 ) {
85319 if (is_file($baseUri)) {
85320 $baseUri = 'file://' . realpath($baseUri);
85321 } elseif (is_dir($baseUri)) {
85322 $baseUri = 'file://' . realpath($baseUri) . '/';
85323 } else {
85324 $baseUri = 'file://' . getcwd() . '/' . $baseUri;
85325 }
85326 }
85327
85328 if ($uri == '') {
85329 return $baseUri;
85330 }
85331
85332 $components = $this->parse($uri);
85333 $path = $components['path'];
85334
85335 if (!empty($components['scheme'])) {
85336 return $uri;
85337 }
85338 $baseComponents = $this->parse($baseUri);
85339 $basePath = $baseComponents['path'];
85340
85341 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
85342 if (isset($components['fragment'])) {
85343 $baseComponents['fragment'] = $components['fragment'];
85344 }
85345
85346 return $this->generate($baseComponents);
85347 }
85348
85349
85350
85351
85352
85353
85354
85355
85356
85357
85358
85359 public static function combineRelativePathWithBasePath($relativePath, $basePath)
85360 {
85361 $relativePath = self::normalizePath($relativePath);
85362 if ($relativePath == '') {
85363 return $basePath;
85364 }
85365 if ($relativePath[0] == '/') {
85366 return $relativePath;
85367 }
85368
85369 $basePathSegments = explode('/', $basePath);
85370
85371 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
85372 $numLevelUp = strlen($match[0]) /3 + 1;
85373 if ($numLevelUp >= count($basePathSegments)) {
85374 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
85375 }
85376
85377 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
85378 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
85379
85380 return implode('/', $basePathSegments) . '/' . $path;
85381 }
85382
85383
85384
85385
85386
85387
85388
85389
85390 private static function normalizePath($path)
85391 {
85392 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
85393 $path = preg_replace('|//|', '/', $path);
85394
85395 return $path;
85396 }
85397
85398
85399
85400
85401
85402
85403 public function isValid($uri)
85404 {
85405 $components = $this->parse($uri);
85406
85407 return !empty($components);
85408 }
85409 }
85410 <?php
85411
85412
85413
85414
85415
85416
85417
85418
85419 namespace JsonSchema\Uri;
85420
85421 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
85422 use JsonSchema\Exception\JsonDecodingException;
85423 use JsonSchema\Exception\ResourceNotFoundException;
85424 use JsonSchema\Uri\Retrievers\FileGetContents;
85425 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
85426 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
85427 use JsonSchema\Validator;
85428
85429
85430
85431
85432
85433
85434 class UriRetriever implements BaseUriRetrieverInterface
85435 {
85436
85437
85438
85439 protected $translationMap = array(
85440
85441 '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
85442 );
85443
85444
85445
85446
85447 protected $allowedInvalidContentTypeEndpoints = array(
85448 'http://json-schema.org/',
85449 'https://json-schema.org/'
85450 );
85451
85452
85453
85454
85455 protected $uriRetriever = null;
85456
85457
85458
85459
85460
85461
85462 private $schemaCache = array();
85463
85464
85465
85466
85467
85468
85469 public function addInvalidContentTypeEndpoint($endpoint)
85470 {
85471 $this->allowedInvalidContentTypeEndpoints[] = $endpoint;
85472 }
85473
85474
85475
85476
85477
85478
85479
85480
85481
85482 public function confirmMediaType($uriRetriever, $uri)
85483 {
85484 $contentType = $uriRetriever->getContentType();
85485
85486 if (is_null($contentType)) {
85487
85488 return;
85489 }
85490
85491 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
85492 return;
85493 }
85494
85495 foreach ($this->allowedInvalidContentTypeEndpoints as $endpoint) {
85496 if (strpos($uri, $endpoint) === 0) {
85497 return true;
85498 }
85499 }
85500
85501 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
85502 }
85503
85504
85505
85506
85507
85508
85509
85510
85511
85512 public function getUriRetriever()
85513 {
85514 if (is_null($this->uriRetriever)) {
85515 $this->setUriRetriever(new FileGetContents());
85516 }
85517
85518 return $this->uriRetriever;
85519 }
85520
85521
85522
85523
85524
85525
85526
85527
85528
85529
85530
85531
85532
85533
85534
85535 public function resolvePointer($jsonSchema, $uri)
85536 {
85537 $resolver = new UriResolver();
85538 $parsed = $resolver->parse($uri);
85539 if (empty($parsed['fragment'])) {
85540 return $jsonSchema;
85541 }
85542
85543 $path = explode('/', $parsed['fragment']);
85544 while ($path) {
85545 $pathElement = array_shift($path);
85546 if (!empty($pathElement)) {
85547 $pathElement = str_replace('~1', '/', $pathElement);
85548 $pathElement = str_replace('~0', '~', $pathElement);
85549 if (!empty($jsonSchema->$pathElement)) {
85550 $jsonSchema = $jsonSchema->$pathElement;
85551 } else {
85552 throw new ResourceNotFoundException(
85553 'Fragment "' . $parsed['fragment'] . '" not found'
85554 . ' in ' . $uri
85555 );
85556 }
85557
85558 if (!is_object($jsonSchema)) {
85559 throw new ResourceNotFoundException(
85560 'Fragment part "' . $pathElement . '" is no object '
85561 . ' in ' . $uri
85562 );
85563 }
85564 }
85565 }
85566
85567 return $jsonSchema;
85568 }
85569
85570
85571
85572
85573 public function retrieve($uri, $baseUri = null, $translate = true)
85574 {
85575 $resolver = new UriResolver();
85576 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
85577
85578
85579 $arParts = $resolver->parse($resolvedUri);
85580 if (isset($arParts['fragment'])) {
85581 unset($arParts['fragment']);
85582 $fetchUri = $resolver->generate($arParts);
85583 }
85584
85585
85586 if ($translate) {
85587 $fetchUri = $this->translate($fetchUri);
85588 }
85589
85590 $jsonSchema = $this->loadSchema($fetchUri);
85591
85592
85593 $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
85594
85595 if ($jsonSchema instanceof \stdClass) {
85596 $jsonSchema->id = $resolvedUri;
85597 }
85598
85599 return $jsonSchema;
85600 }
85601
85602
85603
85604
85605
85606
85607
85608
85609
85610 protected function loadSchema($fetchUri)
85611 {
85612 if (isset($this->schemaCache[$fetchUri])) {
85613 return $this->schemaCache[$fetchUri];
85614 }
85615
85616 $uriRetriever = $this->getUriRetriever();
85617 $contents = $this->uriRetriever->retrieve($fetchUri);
85618 $this->confirmMediaType($uriRetriever, $fetchUri);
85619 $jsonSchema = json_decode($contents);
85620
85621 if (JSON_ERROR_NONE < $error = json_last_error()) {
85622 throw new JsonDecodingException($error);
85623 }
85624
85625 $this->schemaCache[$fetchUri] = $jsonSchema;
85626
85627 return $jsonSchema;
85628 }
85629
85630
85631
85632
85633
85634
85635
85636
85637 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
85638 {
85639 $this->uriRetriever = $uriRetriever;
85640
85641 return $this;
85642 }
85643
85644
85645
85646
85647
85648
85649
85650
85651 public function parse($uri)
85652 {
85653 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
85654
85655 $components = array();
85656 if (5 < count($match)) {
85657 $components = array(
85658 'scheme' => $match[2],
85659 'authority' => $match[4],
85660 'path' => $match[5]
85661 );
85662 }
85663
85664 if (7 < count($match)) {
85665 $components['query'] = $match[7];
85666 }
85667
85668 if (9 < count($match)) {
85669 $components['fragment'] = $match[9];
85670 }
85671
85672 return $components;
85673 }
85674
85675
85676
85677
85678
85679
85680
85681
85682 public function generate(array $components)
85683 {
85684 $uri = $components['scheme'] . '://'
85685 . $components['authority']
85686 . $components['path'];
85687
85688 if (array_key_exists('query', $components)) {
85689 $uri .= $components['query'];
85690 }
85691
85692 if (array_key_exists('fragment', $components)) {
85693 $uri .= $components['fragment'];
85694 }
85695
85696 return $uri;
85697 }
85698
85699
85700
85701
85702
85703
85704
85705
85706
85707 public function resolve($uri, $baseUri = null)
85708 {
85709 $components = $this->parse($uri);
85710 $path = $components['path'];
85711
85712 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
85713 return $uri;
85714 }
85715
85716 $baseComponents = $this->parse($baseUri);
85717 $basePath = $baseComponents['path'];
85718
85719 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
85720
85721 return $this->generate($baseComponents);
85722 }
85723
85724
85725
85726
85727
85728
85729 public function isValid($uri)
85730 {
85731 $components = $this->parse($uri);
85732
85733 return !empty($components);
85734 }
85735
85736
85737
85738
85739 public function setTranslation($from, $to)
85740 {
85741 $this->translationMap[$from] = $to;
85742 }
85743
85744
85745
85746
85747 public function translate($uri)
85748 {
85749 foreach ($this->translationMap as $from => $to) {
85750 $uri = preg_replace($from, $to, $uri);
85751 }
85752
85753
85754 $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
85755
85756 return $uri;
85757 }
85758 }
85759 <?php
85760
85761
85762
85763
85764
85765
85766
85767
85768 namespace JsonSchema;
85769
85770
85771
85772
85773 interface UriResolverInterface
85774 {
85775
85776
85777
85778
85779
85780
85781
85782
85783 public function resolve($uri, $baseUri = null);
85784 }
85785 <?php
85786
85787
85788
85789
85790
85791
85792
85793
85794 namespace JsonSchema;
85795
85796
85797
85798
85799 interface UriRetrieverInterface
85800 {
85801
85802
85803
85804
85805
85806
85807
85808
85809 public function retrieve($uri, $baseUri = null);
85810 }
85811 <?php
85812
85813
85814
85815
85816
85817
85818
85819
85820 namespace JsonSchema;
85821
85822 use JsonSchema\Constraints\BaseConstraint;
85823 use JsonSchema\Constraints\Constraint;
85824
85825
85826
85827
85828
85829
85830
85831
85832
85833 class Validator extends BaseConstraint
85834 {
85835 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
85836
85837 const ERROR_NONE = 0x00000000;
85838 const ERROR_ALL = 0xFFFFFFFF;
85839 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
85840 const ERROR_SCHEMA_VALIDATION = 0x00000002;
85841
85842
85843
85844
85845
85846
85847
85848
85849 public function validate(&$value, $schema = null, $checkMode = null)
85850 {
85851
85852 if (is_array($schema)) {
85853 $schema = self::arrayToObjectRecursive($schema);
85854 }
85855
85856
85857 $initialCheckMode = $this->factory->getConfig();
85858 if ($checkMode !== null) {
85859 $this->factory->setConfig($checkMode);
85860 }
85861
85862
85863 if (is_object($schema) && property_exists($schema, 'id')) {
85864 $schemaURI = $schema->id;
85865 } else {
85866 $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
85867 }
85868 $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
85869
85870 $validator = $this->factory->createInstanceFor('schema');
85871 $validator->check(
85872 $value,
85873 $this->factory->getSchemaStorage()->getSchema($schemaURI)
85874 );
85875
85876 $this->factory->setConfig($initialCheckMode);
85877
85878 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
85879
85880 return $validator->getErrorMask();
85881 }
85882
85883
85884
85885
85886 public function check($value, $schema)
85887 {
85888 return $this->validate($value, $schema);
85889 }
85890
85891
85892
85893
85894 public function coerce(&$value, $schema)
85895 {
85896 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
85897 }
85898 }
85899 Copyright (C) 2015 Composer
85900
85901 Permission is hereby granted, free of charge, to any person obtaining a copy of
85902 this software and associated documentation files (the "Software"), to deal in
85903 the Software without restriction, including without limitation the rights to
85904 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
85905 of the Software, and to permit persons to whom the Software is furnished to do
85906 so, subject to the following conditions:
85907
85908 The above copyright notice and this permission notice shall be included in all
85909 copies or substantial portions of the Software.
85910
85911 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
85912 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85913 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
85914 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
85915 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
85916 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
85917 SOFTWARE.
85918 <?php
85919
85920
85921
85922
85923
85924
85925
85926
85927
85928
85929 namespace Composer\Spdx;
85930
85931 class SpdxLicenses
85932 {
85933
85934 const LICENSES_FILE = 'spdx-licenses.json';
85935
85936
85937 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
85938
85939
85940
85941
85942
85943
85944
85945
85946
85947
85948
85949
85950
85951
85952 private $licenses;
85953
85954
85955
85956
85957 private $licensesExpression;
85958
85959
85960
85961
85962
85963
85964
85965
85966
85967
85968
85969
85970
85971
85972 private $exceptions;
85973
85974
85975
85976
85977 private $exceptionsExpression;
85978
85979 public function __construct()
85980 {
85981 $this->loadLicenses();
85982 $this->loadExceptions();
85983 }
85984
85985
85986
85987
85988
85989
85990
85991
85992
85993
85994
85995
85996
85997 public function getLicenseByIdentifier($identifier)
85998 {
85999 $key = strtolower($identifier);
86000
86001 if (!isset($this->licenses[$key])) {
86002 return null;
86003 }
86004
86005 list($identifier, $name, $isOsiApproved, $isDeprecatedLicenseId) = $this->licenses[$key];
86006
86007 return array(
86008 $name,
86009 $isOsiApproved,
86010 'https://spdx.org/licenses/' . $identifier . '.html#licenseText',
86011 $isDeprecatedLicenseId,
86012 );
86013 }
86014
86015
86016
86017
86018
86019
86020 public function getLicenses()
86021 {
86022 return $this->licenses;
86023 }
86024
86025
86026
86027
86028
86029
86030
86031
86032
86033
86034
86035
86036
86037 public function getExceptionByIdentifier($identifier)
86038 {
86039 $key = strtolower($identifier);
86040
86041 if (!isset($this->exceptions[$key])) {
86042 return null;
86043 }
86044
86045 list($identifier, $name) = $this->exceptions[$key];
86046
86047 return array(
86048 $name,
86049 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText',
86050 );
86051 }
86052
86053
86054
86055
86056
86057
86058
86059
86060 public function getIdentifierByName($name)
86061 {
86062 foreach ($this->licenses as $licenseData) {
86063 if ($licenseData[1] === $name) {
86064 return $licenseData[0];
86065 }
86066 }
86067
86068 foreach ($this->exceptions as $licenseData) {
86069 if ($licenseData[1] === $name) {
86070 return $licenseData[0];
86071 }
86072 }
86073
86074 return null;
86075 }
86076
86077
86078
86079
86080
86081
86082
86083
86084 public function isOsiApprovedByIdentifier($identifier)
86085 {
86086 return $this->licenses[strtolower($identifier)][2];
86087 }
86088
86089
86090
86091
86092
86093
86094
86095
86096 public function isDeprecatedByIdentifier($identifier)
86097 {
86098 return $this->licenses[strtolower($identifier)][3];
86099 }
86100
86101
86102
86103
86104
86105
86106
86107
86108 public function validate($license)
86109 {
86110 if (is_array($license)) {
86111 $count = count($license);
86112 if ($count !== count(array_filter($license, 'is_string'))) {
86113 throw new \InvalidArgumentException('Array of strings expected.');
86114 }
86115 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
86116 }
86117
86118 if (!is_string($license)) {
86119 throw new \InvalidArgumentException(sprintf(
86120 'Array or String expected, %s given.',
86121 gettype($license)
86122 ));
86123 }
86124
86125 return $this->isValidLicenseString($license);
86126 }
86127
86128
86129
86130
86131 public static function getResourcesDir()
86132 {
86133 return dirname(__DIR__) . '/res';
86134 }
86135
86136
86137
86138
86139 private function loadLicenses()
86140 {
86141 if (null !== $this->licenses) {
86142 return;
86143 }
86144
86145 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
86146 if (false === $json) {
86147 throw new \RuntimeException('Missing license file in ' . self::getResourcesDir() . '/' . self::LICENSES_FILE);
86148 }
86149 $this->licenses = array();
86150
86151 foreach (json_decode($json, true) as $identifier => $license) {
86152 $this->licenses[strtolower($identifier)] = array($identifier, $license[0], $license[1], $license[2]);
86153 }
86154 }
86155
86156
86157
86158
86159 private function loadExceptions()
86160 {
86161 if (null !== $this->exceptions) {
86162 return;
86163 }
86164
86165 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
86166 if (false === $json) {
86167 throw new \RuntimeException('Missing exceptions file in ' . self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
86168 }
86169 $this->exceptions = array();
86170
86171 foreach (json_decode($json, true) as $identifier => $exception) {
86172 $this->exceptions[strtolower($identifier)] = array($identifier, $exception[0]);
86173 }
86174 }
86175
86176
86177
86178
86179 private function getLicensesExpression()
86180 {
86181 if (null === $this->licensesExpression) {
86182 $licenses = array_map('preg_quote', array_keys($this->licenses));
86183 rsort($licenses);
86184 $licenses = implode('|', $licenses);
86185 $this->licensesExpression = $licenses;
86186 }
86187
86188 return $this->licensesExpression;
86189 }
86190
86191
86192
86193
86194 private function getExceptionsExpression()
86195 {
86196 if (null === $this->exceptionsExpression) {
86197 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
86198 rsort($exceptions);
86199 $exceptions = implode('|', $exceptions);
86200 $this->exceptionsExpression = $exceptions;
86201 }
86202
86203 return $this->exceptionsExpression;
86204 }
86205
86206
86207
86208
86209
86210
86211
86212
86213 private function isValidLicenseString($license)
86214 {
86215 if (isset($this->licenses[strtolower($license)])) {
86216 return true;
86217 }
86218
86219 $licenses = $this->getLicensesExpression();
86220 $exceptions = $this->getExceptionsExpression();
86221
86222 $regex = <<<REGEX
86223 {
86224 (?(DEFINE)
86225     # idstring: 1*( ALPHA / DIGIT / - / . )
86226     (?<idstring>[\pL\pN.-]{1,})
86227
86228     # license-id: taken from list
86229     (?<licenseid>${licenses})
86230
86231     # license-exception-id: taken from list
86232     (?<licenseexceptionid>${exceptions})
86233
86234     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
86235     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
86236
86237     # simple-expresssion: license-id / license-id+ / license-ref
86238     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
86239
86240     # compound-expression: 1*(
86241     #   simple-expression /
86242     #   simple-expression WITH license-exception-id /
86243     #   compound-expression AND compound-expression /
86244     #   compound-expression OR compound-expression
86245     # ) / ( compound-expression ) )
86246     (?<compound_head>
86247         (?&simple_expression) ( \s+ WITH \s+ (?&licenseexceptionid))?
86248             | \( \s* (?&compound_expression) \s* \)
86249     )
86250     (?<compound_expression>
86251         (?&compound_head) (?: \s+ (?:AND|OR) \s+ (?&compound_expression))?
86252     )
86253
86254     # license-expression: 1*1(simple-expression / compound-expression)
86255     (?<license_expression>(?&compound_expression) | (?&simple_expression))
86256 ) # end of define
86257
86258 ^(NONE | NOASSERTION | (?&license_expression))$
86259 }xi
86260 REGEX;
86261
86262 $match = preg_match($regex, $license);
86263
86264 if (0 === $match) {
86265 return false;
86266 }
86267
86268 if (false === $match) {
86269 throw new \RuntimeException('Regex failed to compile/run.');
86270 }
86271
86272 return true;
86273 }
86274 }
86275 Copyright (C) 2015 Composer
86276
86277 Permission is hereby granted, free of charge, to any person obtaining a copy of
86278 this software and associated documentation files (the "Software"), to deal in
86279 the Software without restriction, including without limitation the rights to
86280 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
86281 of the Software, and to permit persons to whom the Software is furnished to do
86282 so, subject to the following conditions:
86283
86284 The above copyright notice and this permission notice shall be included in all
86285 copies or substantial portions of the Software.
86286
86287 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86288 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86289 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86290 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86291 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
86292 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
86293 SOFTWARE.
86294 <?php
86295
86296
86297
86298
86299
86300
86301
86302
86303
86304
86305 namespace Composer\Semver;
86306
86307 use Composer\Semver\Constraint\Constraint;
86308
86309 class Comparator
86310 {
86311
86312
86313
86314
86315
86316
86317
86318
86319 public static function greaterThan($version1, $version2)
86320 {
86321 return self::compare($version1, '>', $version2);
86322 }
86323
86324
86325
86326
86327
86328
86329
86330
86331
86332 public static function greaterThanOrEqualTo($version1, $version2)
86333 {
86334 return self::compare($version1, '>=', $version2);
86335 }
86336
86337
86338
86339
86340
86341
86342
86343
86344
86345 public static function lessThan($version1, $version2)
86346 {
86347 return self::compare($version1, '<', $version2);
86348 }
86349
86350
86351
86352
86353
86354
86355
86356
86357
86358 public static function lessThanOrEqualTo($version1, $version2)
86359 {
86360 return self::compare($version1, '<=', $version2);
86361 }
86362
86363
86364
86365
86366
86367
86368
86369
86370
86371 public static function equalTo($version1, $version2)
86372 {
86373 return self::compare($version1, '==', $version2);
86374 }
86375
86376
86377
86378
86379
86380
86381
86382
86383
86384 public static function notEqualTo($version1, $version2)
86385 {
86386 return self::compare($version1, '!=', $version2);
86387 }
86388
86389
86390
86391
86392
86393
86394
86395
86396
86397
86398 public static function compare($version1, $operator, $version2)
86399 {
86400 $constraint = new Constraint($operator, $version2);
86401
86402 return $constraint->matches(new Constraint('==', $version1));
86403 }
86404 }
86405 <?php
86406
86407
86408
86409
86410
86411
86412
86413
86414
86415
86416 namespace Composer\Semver\Constraint;
86417
86418 trigger_error('The ' . __NAMESPACE__ . '\AbstractConstraint abstract class is deprecated, there is no replacement for it, it will be removed in the next major version.', E_USER_DEPRECATED);
86419
86420
86421
86422
86423 abstract class AbstractConstraint implements ConstraintInterface
86424 {
86425
86426 protected $prettyString;
86427
86428
86429
86430
86431
86432
86433 public function matches(ConstraintInterface $provider)
86434 {
86435 if ($provider instanceof $this) {
86436
86437 return $this->matchSpecific($provider);
86438 }
86439
86440
86441 return $provider->matches($this);
86442 }
86443
86444
86445
86446
86447 public function setPrettyString($prettyString)
86448 {
86449 $this->prettyString = $prettyString;
86450 }
86451
86452
86453
86454
86455 public function getPrettyString()
86456 {
86457 if ($this->prettyString) {
86458 return $this->prettyString;
86459 }
86460
86461 return $this->__toString();
86462 }
86463
86464
86465
86466
86467 }
86468 <?php
86469
86470
86471
86472
86473
86474
86475
86476
86477
86478
86479 namespace Composer\Semver\Constraint;
86480
86481
86482
86483
86484 class Constraint implements ConstraintInterface
86485 {
86486
86487 const OP_EQ = 0;
86488 const OP_LT = 1;
86489 const OP_LE = 2;
86490 const OP_GT = 3;
86491 const OP_GE = 4;
86492 const OP_NE = 5;
86493
86494
86495
86496
86497
86498
86499 private static $transOpStr = array(
86500 '=' => self::OP_EQ,
86501 '==' => self::OP_EQ,
86502 '<' => self::OP_LT,
86503 '<=' => self::OP_LE,
86504 '>' => self::OP_GT,
86505 '>=' => self::OP_GE,
86506 '<>' => self::OP_NE,
86507 '!=' => self::OP_NE,
86508 );
86509
86510
86511
86512
86513
86514
86515 private static $transOpInt = array(
86516 self::OP_EQ => '==',
86517 self::OP_LT => '<',
86518 self::OP_LE => '<=',
86519 self::OP_GT => '>',
86520 self::OP_GE => '>=',
86521 self::OP_NE => '!=',
86522 );
86523
86524
86525 protected $operator;
86526
86527
86528 protected $version;
86529
86530
86531 protected $prettyString;
86532
86533
86534
86535
86536
86537
86538 public function matches(ConstraintInterface $provider)
86539 {
86540 if ($provider instanceof $this) {
86541 return $this->matchSpecific($provider);
86542 }
86543
86544
86545 return $provider->matches($this);
86546 }
86547
86548
86549
86550
86551 public function setPrettyString($prettyString)
86552 {
86553 $this->prettyString = $prettyString;
86554 }
86555
86556
86557
86558
86559 public function getPrettyString()
86560 {
86561 if ($this->prettyString) {
86562 return $this->prettyString;
86563 }
86564
86565 return $this->__toString();
86566 }
86567
86568
86569
86570
86571
86572
86573 public static function getSupportedOperators()
86574 {
86575 return array_keys(self::$transOpStr);
86576 }
86577
86578
86579
86580
86581
86582
86583
86584
86585
86586 public function __construct($operator, $version)
86587 {
86588 if (!isset(self::$transOpStr[$operator])) {
86589 throw new \InvalidArgumentException(sprintf(
86590 'Invalid operator "%s" given, expected one of: %s',
86591 $operator,
86592 implode(', ', self::getSupportedOperators())
86593 ));
86594 }
86595
86596 $this->operator = self::$transOpStr[$operator];
86597 $this->version = $version;
86598 }
86599
86600
86601
86602
86603
86604
86605
86606
86607
86608
86609
86610 public function versionCompare($a, $b, $operator, $compareBranches = false)
86611 {
86612 if (!isset(self::$transOpStr[$operator])) {
86613 throw new \InvalidArgumentException(sprintf(
86614 'Invalid operator "%s" given, expected one of: %s',
86615 $operator,
86616 implode(', ', self::getSupportedOperators())
86617 ));
86618 }
86619
86620 $aIsBranch = 'dev-' === substr($a, 0, 4);
86621 $bIsBranch = 'dev-' === substr($b, 0, 4);
86622
86623 if ($aIsBranch && $bIsBranch) {
86624 return $operator === '==' && $a === $b;
86625 }
86626
86627
86628 if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
86629 return false;
86630 }
86631
86632 return version_compare($a, $b, $operator);
86633 }
86634
86635
86636
86637
86638
86639
86640
86641 public function matchSpecific(Constraint $provider, $compareBranches = false)
86642 {
86643 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
86644 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
86645
86646 $isEqualOp = self::OP_EQ === $this->operator;
86647 $isNonEqualOp = self::OP_NE === $this->operator;
86648 $isProviderEqualOp = self::OP_EQ === $provider->operator;
86649 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
86650
86651
86652
86653 if ($isNonEqualOp || $isProviderNonEqualOp) {
86654 return (!$isEqualOp && !$isProviderEqualOp)
86655 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
86656 }
86657
86658
86659
86660 if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
86661 return true;
86662 }
86663
86664 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
86665
86666
86667 return !($provider->version === $this->version
86668 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
86669 && self::$transOpInt[$this->operator] !== $noEqualOp);
86670 }
86671
86672 return false;
86673 }
86674
86675
86676
86677
86678 public function __toString()
86679 {
86680 return self::$transOpInt[$this->operator] . ' ' . $this->version;
86681 }
86682 }
86683 <?php
86684
86685
86686
86687
86688
86689
86690
86691
86692
86693
86694 namespace Composer\Semver\Constraint;
86695
86696 interface ConstraintInterface
86697 {
86698
86699
86700
86701
86702
86703 public function matches(ConstraintInterface $provider);
86704
86705
86706
86707
86708 public function getPrettyString();
86709
86710
86711
86712
86713 public function __toString();
86714 }
86715 <?php
86716
86717
86718
86719
86720
86721
86722
86723
86724
86725
86726 namespace Composer\Semver\Constraint;
86727
86728
86729
86730
86731 class EmptyConstraint implements ConstraintInterface
86732 {
86733
86734 protected $prettyString;
86735
86736
86737
86738
86739
86740
86741 public function matches(ConstraintInterface $provider)
86742 {
86743 return true;
86744 }
86745
86746
86747
86748
86749 public function setPrettyString($prettyString)
86750 {
86751 $this->prettyString = $prettyString;
86752 }
86753
86754
86755
86756
86757 public function getPrettyString()
86758 {
86759 if ($this->prettyString) {
86760 return $this->prettyString;
86761 }
86762
86763 return (string) $this;
86764 }
86765
86766
86767
86768
86769 public function __toString()
86770 {
86771 return '[]';
86772 }
86773 }
86774 <?php
86775
86776
86777
86778
86779
86780
86781
86782
86783
86784
86785 namespace Composer\Semver\Constraint;
86786
86787
86788
86789
86790 class MultiConstraint implements ConstraintInterface
86791 {
86792
86793 protected $constraints;
86794
86795
86796 protected $prettyString;
86797
86798
86799 protected $conjunctive;
86800
86801
86802
86803
86804
86805 public function __construct(array $constraints, $conjunctive = true)
86806 {
86807 $this->constraints = $constraints;
86808 $this->conjunctive = $conjunctive;
86809 }
86810
86811
86812
86813
86814 public function getConstraints()
86815 {
86816 return $this->constraints;
86817 }
86818
86819
86820
86821
86822 public function isConjunctive()
86823 {
86824 return $this->conjunctive;
86825 }
86826
86827
86828
86829
86830 public function isDisjunctive()
86831 {
86832 return !$this->conjunctive;
86833 }
86834
86835
86836
86837
86838
86839
86840 public function matches(ConstraintInterface $provider)
86841 {
86842 if (false === $this->conjunctive) {
86843 foreach ($this->constraints as $constraint) {
86844 if ($constraint->matches($provider)) {
86845 return true;
86846 }
86847 }
86848
86849 return false;
86850 }
86851
86852 foreach ($this->constraints as $constraint) {
86853 if (!$constraint->matches($provider)) {
86854 return false;
86855 }
86856 }
86857
86858 return true;
86859 }
86860
86861
86862
86863
86864 public function setPrettyString($prettyString)
86865 {
86866 $this->prettyString = $prettyString;
86867 }
86868
86869
86870
86871
86872 public function getPrettyString()
86873 {
86874 if ($this->prettyString) {
86875 return $this->prettyString;
86876 }
86877
86878 return (string) $this;
86879 }
86880
86881
86882
86883
86884 public function __toString()
86885 {
86886 $constraints = array();
86887 foreach ($this->constraints as $constraint) {
86888 $constraints[] = (string) $constraint;
86889 }
86890
86891 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
86892 }
86893 }
86894 <?php
86895
86896
86897
86898
86899
86900
86901
86902
86903
86904
86905 namespace Composer\Semver;
86906
86907 use Composer\Semver\Constraint\Constraint;
86908
86909 class Semver
86910 {
86911 const SORT_ASC = 1;
86912 const SORT_DESC = -1;
86913
86914
86915 private static $versionParser;
86916
86917
86918
86919
86920
86921
86922
86923
86924
86925 public static function satisfies($version, $constraints)
86926 {
86927 if (null === self::$versionParser) {
86928 self::$versionParser = new VersionParser();
86929 }
86930
86931 $versionParser = self::$versionParser;
86932 $provider = new Constraint('==', $versionParser->normalize($version));
86933 $parsedConstraints = $versionParser->parseConstraints($constraints);
86934
86935 return $parsedConstraints->matches($provider);
86936 }
86937
86938
86939
86940
86941
86942
86943
86944
86945
86946 public static function satisfiedBy(array $versions, $constraints)
86947 {
86948 $versions = array_filter($versions, function ($version) use ($constraints) {
86949 return Semver::satisfies($version, $constraints);
86950 });
86951
86952 return array_values($versions);
86953 }
86954
86955
86956
86957
86958
86959
86960
86961
86962 public static function sort(array $versions)
86963 {
86964 return self::usort($versions, self::SORT_ASC);
86965 }
86966
86967
86968
86969
86970
86971
86972
86973
86974 public static function rsort(array $versions)
86975 {
86976 return self::usort($versions, self::SORT_DESC);
86977 }
86978
86979
86980
86981
86982
86983
86984
86985 private static function usort(array $versions, $direction)
86986 {
86987 if (null === self::$versionParser) {
86988 self::$versionParser = new VersionParser();
86989 }
86990
86991 $versionParser = self::$versionParser;
86992 $normalized = array();
86993
86994
86995
86996 foreach ($versions as $key => $version) {
86997 $normalized[] = array($versionParser->normalize($version), $key);
86998 }
86999
87000 usort($normalized, function (array $left, array $right) use ($direction) {
87001 if ($left[0] === $right[0]) {
87002 return 0;
87003 }
87004
87005 if (Comparator::lessThan($left[0], $right[0])) {
87006 return -$direction;
87007 }
87008
87009 return $direction;
87010 });
87011
87012
87013 $sorted = array();
87014 foreach ($normalized as $item) {
87015 $sorted[] = $versions[$item[1]];
87016 }
87017
87018 return $sorted;
87019 }
87020 }
87021 <?php
87022
87023
87024
87025
87026
87027
87028
87029
87030
87031
87032 namespace Composer\Semver;
87033
87034 use Composer\Semver\Constraint\ConstraintInterface;
87035 use Composer\Semver\Constraint\EmptyConstraint;
87036 use Composer\Semver\Constraint\MultiConstraint;
87037 use Composer\Semver\Constraint\Constraint;
87038
87039
87040
87041
87042
87043
87044 class VersionParser
87045 {
87046
87047
87048
87049
87050
87051
87052
87053
87054
87055
87056
87057
87058
87059 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
87060
87061
87062 private static $stabilitiesRegex = 'stable|RC|beta|alpha|dev';
87063
87064
87065
87066
87067
87068
87069
87070
87071 public static function parseStability($version)
87072 {
87073 $version = preg_replace('{#.+$}i', '', $version);
87074
87075 if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) {
87076 return 'dev';
87077 }
87078
87079 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
87080
87081 if (!empty($match[3])) {
87082 return 'dev';
87083 }
87084
87085 if (!empty($match[1])) {
87086 if ('beta' === $match[1] || 'b' === $match[1]) {
87087 return 'beta';
87088 }
87089 if ('alpha' === $match[1] || 'a' === $match[1]) {
87090 return 'alpha';
87091 }
87092 if ('rc' === $match[1]) {
87093 return 'RC';
87094 }
87095 }
87096
87097 return 'stable';
87098 }
87099
87100
87101
87102
87103
87104
87105 public static function normalizeStability($stability)
87106 {
87107 $stability = strtolower($stability);
87108
87109 return $stability === 'rc' ? 'RC' : $stability;
87110 }
87111
87112
87113
87114
87115
87116
87117
87118
87119
87120
87121
87122 public function normalize($version, $fullVersion = null)
87123 {
87124 $version = trim($version);
87125 $origVersion = $version;
87126 if (null === $fullVersion) {
87127 $fullVersion = $version;
87128 }
87129
87130
87131 if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
87132 $version = $match[1];
87133 }
87134
87135
87136 if (preg_match('{@(?:' . self::$stabilitiesRegex . ')$}i', $version, $match)) {
87137 $version = substr($version, 0, strlen($version) - strlen($match[0]));
87138 }
87139
87140
87141 if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
87142 return '9999999-dev';
87143 }
87144
87145
87146 if (stripos($version, 'dev-') === 0) {
87147 return 'dev-' . substr($version, 4);
87148 }
87149
87150
87151 if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
87152 $version = $match[1];
87153 }
87154
87155
87156 if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
87157 $version = $matches[1]
87158 . (!empty($matches[2]) ? $matches[2] : '.0')
87159 . (!empty($matches[3]) ? $matches[3] : '.0')
87160 . (!empty($matches[4]) ? $matches[4] : '.0');
87161 $index = 5;
87162
87163 } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
87164 $version = preg_replace('{\D}', '.', $matches[1]);
87165 $index = 2;
87166 }
87167
87168
87169 if (isset($index)) {
87170 if (!empty($matches[$index])) {
87171 if ('stable' === $matches[$index]) {
87172 return $version;
87173 }
87174 $version .= '-' . $this->expandStability($matches[$index]) . (isset($matches[$index + 1]) && '' !== $matches[$index + 1] ? ltrim($matches[$index + 1], '.-') : '');
87175 }
87176
87177 if (!empty($matches[$index + 2])) {
87178 $version .= '-dev';
87179 }
87180
87181 return $version;
87182 }
87183
87184
87185 if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
87186 try {
87187 $normalized = $this->normalizeBranch($match[1]);
87188
87189
87190
87191 if (strpos($normalized, 'dev-') === false) {
87192 return $normalized;
87193 }
87194 } catch (\Exception $e) {
87195 }
87196 }
87197
87198 $extraMessage = '';
87199 if (preg_match('{ +as +' . preg_quote($version) . '(?:@(?:'.self::$stabilitiesRegex.'))?$}', $fullVersion)) {
87200 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
87201 } elseif (preg_match('{^' . preg_quote($version) . '(?:@(?:'.self::$stabilitiesRegex.'))? +as +}', $fullVersion)) {
87202 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
87203 }
87204
87205 throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage);
87206 }
87207
87208
87209
87210
87211
87212
87213
87214
87215 public function parseNumericAliasPrefix($branch)
87216 {
87217 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
87218 return $matches['version'] . '.';
87219 }
87220
87221 return false;
87222 }
87223
87224
87225
87226
87227
87228
87229
87230
87231 public function normalizeBranch($name)
87232 {
87233 $name = trim($name);
87234
87235 if (in_array($name, array('master', 'trunk', 'default'))) {
87236 return $this->normalize($name);
87237 }
87238
87239 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
87240 $version = '';
87241 for ($i = 1; $i < 5; ++$i) {
87242 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
87243 }
87244
87245 return str_replace('x', '9999999', $version) . '-dev';
87246 }
87247
87248 return 'dev-' . $name;
87249 }
87250
87251
87252
87253
87254
87255
87256
87257
87258 public function parseConstraints($constraints)
87259 {
87260 $prettyConstraint = $constraints;
87261
87262 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
87263 $orGroups = array();
87264
87265 foreach ($orConstraints as $constraints) {
87266 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
87267 if (count($andConstraints) > 1) {
87268 $constraintObjects = array();
87269 foreach ($andConstraints as $constraint) {
87270 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
87271 $constraintObjects[] = $parsedConstraint;
87272 }
87273 }
87274 } else {
87275 $constraintObjects = $this->parseConstraint($andConstraints[0]);
87276 }
87277
87278 if (1 === count($constraintObjects)) {
87279 $constraint = $constraintObjects[0];
87280 } else {
87281 $constraint = new MultiConstraint($constraintObjects);
87282 }
87283
87284 $orGroups[] = $constraint;
87285 }
87286
87287 if (1 === count($orGroups)) {
87288 $constraint = $orGroups[0];
87289 } elseif (2 === count($orGroups)
87290
87291
87292 && $orGroups[0] instanceof MultiConstraint
87293 && $orGroups[1] instanceof MultiConstraint
87294 && 2 === count($orGroups[0]->getConstraints())
87295 && 2 === count($orGroups[1]->getConstraints())
87296 && ($a = (string) $orGroups[0])
87297 && strpos($a, '[>=') === 0 && (false !== ($posA = strpos($a, '<', 4)))
87298 && ($b = (string) $orGroups[1])
87299 && strpos($b, '[>=') === 0 && (false !== ($posB = strpos($b, '<', 4)))
87300 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
87301 ) {
87302 $constraint = new MultiConstraint(array(
87303 new Constraint('>=', substr($a, 4, $posA - 5)),
87304 new Constraint('<', substr($b, $posB + 2, -1)),
87305 ));
87306 } else {
87307 $constraint = new MultiConstraint($orGroups, false);
87308 }
87309
87310 $constraint->setPrettyString($prettyConstraint);
87311
87312 return $constraint;
87313 }
87314
87315
87316
87317
87318
87319
87320
87321
87322 private function parseConstraint($constraint)
87323 {
87324
87325 if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $constraint, $match)) {
87326 $constraint = $match[1];
87327 }
87328
87329
87330 if (preg_match('{^([^,\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) {
87331 $constraint = '' !== $match[1] ? $match[1] : '*';
87332 if ($match[2] !== 'stable') {
87333 $stabilityModifier = $match[2];
87334 }
87335 }
87336
87337
87338 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraint, $match)) {
87339 $constraint = $match[1];
87340 }
87341
87342 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
87343 return array(new EmptyConstraint());
87344 }
87345
87346 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?(?:' . self::$modifierRegex . '|\.([xX*][.-]?dev))(?:\+[^\s]+)?';
87347
87348
87349
87350
87351
87352
87353 if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
87354 if (strpos($constraint, '~>') === 0) {
87355 throw new \UnexpectedValueException(
87356 'Could not parse version constraint ' . $constraint . ': ' .
87357 'Invalid operator "~>", you probably meant to use the "~" operator'
87358 );
87359 }
87360
87361
87362 if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
87363 $position = 4;
87364 } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
87365 $position = 3;
87366 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
87367 $position = 2;
87368 } else {
87369 $position = 1;
87370 }
87371
87372
87373 if (!empty($matches[8])) {
87374 $position++;
87375 }
87376
87377
87378 $stabilitySuffix = '';
87379 if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) {
87380 $stabilitySuffix .= '-dev';
87381 }
87382
87383 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
87384 $lowerBound = new Constraint('>=', $lowVersion);
87385
87386
87387
87388 $highPosition = max(1, $position - 1);
87389 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
87390 $upperBound = new Constraint('<', $highVersion);
87391
87392 return array(
87393 $lowerBound,
87394 $upperBound,
87395 );
87396 }
87397
87398
87399
87400
87401
87402
87403 if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
87404
87405 if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
87406 $position = 1;
87407 } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
87408 $position = 2;
87409 } else {
87410 $position = 3;
87411 }
87412
87413
87414 $stabilitySuffix = '';
87415 if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) {
87416 $stabilitySuffix .= '-dev';
87417 }
87418
87419 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
87420 $lowerBound = new Constraint('>=', $lowVersion);
87421
87422
87423
87424 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
87425 $upperBound = new Constraint('<', $highVersion);
87426
87427 return array(
87428 $lowerBound,
87429 $upperBound,
87430 );
87431 }
87432
87433
87434
87435
87436
87437 if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
87438 if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
87439 $position = 3;
87440 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
87441 $position = 2;
87442 } else {
87443 $position = 1;
87444 }
87445
87446 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
87447 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
87448
87449 if ($lowVersion === '0.0.0.0-dev') {
87450 return array(new Constraint('<', $highVersion));
87451 }
87452
87453 return array(
87454 new Constraint('>=', $lowVersion),
87455 new Constraint('<', $highVersion),
87456 );
87457 }
87458
87459
87460
87461
87462
87463
87464
87465 if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
87466
87467 $lowStabilitySuffix = '';
87468 if (empty($matches[6]) && empty($matches[8]) && empty($matches[9])) {
87469 $lowStabilitySuffix = '-dev';
87470 }
87471
87472 $lowVersion = $this->normalize($matches['from']);
87473 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
87474
87475 $empty = function ($x) {
87476 return ($x === 0 || $x === '0') ? false : empty($x);
87477 };
87478
87479 if ((!$empty($matches[12]) && !$empty($matches[13])) || !empty($matches[15]) || !empty($matches[17]) || !empty($matches[18])) {
87480 $highVersion = $this->normalize($matches['to']);
87481 $upperBound = new Constraint('<=', $highVersion);
87482 } else {
87483 $highMatch = array('', $matches[11], $matches[12], $matches[13], $matches[14]);
87484
87485
87486 $this->normalize($matches['to']);
87487
87488 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[12]) ? 1 : 2, 1) . '-dev';
87489 $upperBound = new Constraint('<', $highVersion);
87490 }
87491
87492 return array(
87493 $lowerBound,
87494 $upperBound,
87495 );
87496 }
87497
87498
87499 if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
87500 try {
87501 try {
87502 $version = $this->normalize($matches[2]);
87503 } catch (\UnexpectedValueException $e) {
87504
87505
87506 if (substr($matches[2], -4) === '-dev' && preg_match('{^[0-9a-zA-Z-./]+$}', $matches[2])) {
87507 $version = $this->normalize('dev-'.substr($matches[2], 0, -4));
87508 } else {
87509 throw $e;
87510 }
87511 }
87512
87513 $op = $matches[1] ?: '=';
87514
87515 if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') {
87516 $version .= '-' . $stabilityModifier;
87517 } elseif ('<' === $op || '>=' === $op) {
87518 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
87519 if (strpos($matches[2], 'dev-') !== 0) {
87520 $version .= '-dev';
87521 }
87522 }
87523 }
87524
87525 return array(new Constraint($matches[1] ?: '=', $version));
87526 } catch (\Exception $e) {
87527 }
87528 }
87529
87530 $message = 'Could not parse version constraint ' . $constraint;
87531 if (isset($e)) {
87532 $message .= ': ' . $e->getMessage();
87533 }
87534
87535 throw new \UnexpectedValueException($message);
87536 }
87537
87538
87539
87540
87541
87542
87543
87544
87545
87546
87547
87548
87549
87550 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
87551 {
87552 for ($i = 4; $i > 0; --$i) {
87553 if ($i > $position) {
87554 $matches[$i] = $pad;
87555 } elseif ($i === $position && $increment) {
87556 $matches[$i] += $increment;
87557
87558 if ($matches[$i] < 0) {
87559 $matches[$i] = $pad;
87560 --$position;
87561
87562
87563 if ($i === 1) {
87564 return null;
87565 }
87566 }
87567 }
87568 }
87569
87570 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
87571 }
87572
87573
87574
87575
87576
87577
87578
87579
87580 private function expandStability($stability)
87581 {
87582 $stability = strtolower($stability);
87583
87584 switch ($stability) {
87585 case 'a':
87586 return 'alpha';
87587 case 'b':
87588 return 'beta';
87589 case 'p':
87590 case 'pl':
87591 return 'patch';
87592 case 'rc':
87593 return 'RC';
87594 default:
87595 return $stability;
87596 }
87597 }
87598 }
87599 Copyright (C) 2016 Composer
87600
87601 Permission is hereby granted, free of charge, to any person obtaining a copy of
87602 this software and associated documentation files (the "Software"), to deal in
87603 the Software without restriction, including without limitation the rights to
87604 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
87605 of the Software, and to permit persons to whom the Software is furnished to do
87606 so, subject to the following conditions:
87607
87608 The above copyright notice and this permission notice shall be included in all
87609 copies or substantial portions of the Software.
87610
87611 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
87612 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87613 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
87614 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87615 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
87616 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
87617 SOFTWARE.
87618 <?php
87619
87620
87621
87622
87623
87624
87625
87626
87627
87628
87629 namespace Composer\CaBundle;
87630
87631 use Psr\Log\LoggerInterface;
87632 use Symfony\Component\Process\PhpProcess;
87633
87634
87635
87636
87637
87638 class CaBundle
87639 {
87640
87641 private static $caPath;
87642
87643 private static $caFileValidity = array();
87644
87645 private static $useOpensslParse;
87646
87647
87648
87649
87650
87651
87652
87653
87654
87655
87656
87657
87658
87659
87660
87661
87662
87663
87664
87665
87666
87667
87668
87669
87670
87671
87672
87673
87674
87675
87676
87677
87678
87679
87680
87681
87682
87683
87684 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
87685 {
87686 if (self::$caPath !== null) {
87687 return self::$caPath;
87688 }
87689 $caBundlePaths = array();
87690
87691
87692
87693 $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
87694
87695
87696
87697 $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
87698
87699 $caBundlePaths[] = ini_get('openssl.cafile');
87700 $caBundlePaths[] = ini_get('openssl.capath');
87701
87702 $otherLocations = array(
87703 '/etc/pki/tls/certs/ca-bundle.crt', 
87704 '/etc/ssl/certs/ca-certificates.crt', 
87705 '/etc/ssl/ca-bundle.pem', 
87706 '/usr/local/share/certs/ca-root-nss.crt', 
87707 '/usr/ssl/certs/ca-bundle.crt', 
87708 '/opt/local/share/curl/curl-ca-bundle.crt', 
87709 '/usr/local/share/curl/curl-ca-bundle.crt', 
87710 '/usr/share/ssl/certs/ca-bundle.crt', 
87711 '/etc/ssl/cert.pem', 
87712 '/usr/local/etc/ssl/cert.pem', 
87713 '/usr/local/etc/openssl/cert.pem', 
87714 '/usr/local/etc/openssl@1.1/cert.pem', 
87715 );
87716
87717 foreach($otherLocations as $location) {
87718 $otherLocations[] = dirname($location);
87719 }
87720
87721 $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
87722
87723 foreach ($caBundlePaths as $caBundle) {
87724 if ($caBundle && self::caFileUsable($caBundle, $logger)) {
87725 return self::$caPath = $caBundle;
87726 }
87727
87728 if ($caBundle && self::caDirUsable($caBundle, $logger)) {
87729 return self::$caPath = $caBundle;
87730 }
87731 }
87732
87733 return self::$caPath = static::getBundledCaBundlePath(); 
87734 }
87735
87736
87737
87738
87739
87740
87741
87742
87743 public static function getBundledCaBundlePath()
87744 {
87745 $caBundleFile = __DIR__.'/../res/cacert.pem';
87746
87747
87748
87749 if (0 === strpos($caBundleFile, 'phar://')) {
87750 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-');
87751 if (false === $tempCaBundleFile) {
87752 throw new \RuntimeException('Could not create a temporary file to store the bundled CA file');
87753 }
87754
87755 file_put_contents(
87756 $tempCaBundleFile,
87757 file_get_contents($caBundleFile)
87758 );
87759
87760 register_shutdown_function(function() use ($tempCaBundleFile) {
87761 @unlink($tempCaBundleFile);
87762 });
87763
87764 $caBundleFile = $tempCaBundleFile;
87765 }
87766
87767 return $caBundleFile;
87768 }
87769
87770
87771
87772
87773
87774
87775
87776
87777
87778 public static function validateCaFile($filename, LoggerInterface $logger = null)
87779 {
87780 static $warned = false;
87781
87782 if (isset(self::$caFileValidity[$filename])) {
87783 return self::$caFileValidity[$filename];
87784 }
87785
87786 $contents = file_get_contents($filename);
87787
87788
87789
87790 if (!static::isOpensslParseSafe()) {
87791 if (!$warned && $logger) {
87792 $logger->warning(sprintf(
87793 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
87794 PHP_VERSION
87795 ));
87796 $warned = true;
87797 }
87798
87799 $isValid = !empty($contents);
87800 } elseif (is_string($contents) && strlen($contents) > 0) {
87801 $contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
87802 if (null === $contents) {
87803
87804 $isValid = false;
87805 } else {
87806 $isValid = (bool) openssl_x509_parse($contents);
87807 }
87808 } else {
87809 $isValid = false;
87810 }
87811
87812 if ($logger) {
87813 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
87814 }
87815
87816 return self::$caFileValidity[$filename] = $isValid;
87817 }
87818
87819
87820
87821
87822
87823
87824
87825
87826
87827 public static function isOpensslParseSafe()
87828 {
87829 if (null !== self::$useOpensslParse) {
87830 return self::$useOpensslParse;
87831 }
87832
87833 if (PHP_VERSION_ID >= 50600) {
87834 return self::$useOpensslParse = true;
87835 }
87836
87837
87838
87839
87840
87841 if (
87842 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
87843 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
87844 || PHP_VERSION_ID >= 50507
87845 ) {
87846
87847 return self::$useOpensslParse = true;
87848 }
87849
87850 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
87851
87852 return self::$useOpensslParse = false;
87853 }
87854
87855 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
87856 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
87857
87858 if (preg_match($regex, PHP_VERSION, $m)) {
87859 return ((int) $m[1]) >= $fixedVersion;
87860 }
87861
87862 return false;
87863 };
87864
87865
87866 if (
87867 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
87868 || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
87869 || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
87870 ) {
87871 return self::$useOpensslParse = true;
87872 }
87873
87874
87875 if (!class_exists('Symfony\Component\Process\PhpProcess')) {
87876 return self::$useOpensslParse = false;
87877 }
87878
87879
87880
87881
87882
87883
87884
87885
87886
87887
87888 $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
87889 $script = <<<'EOT'
87890
87891 error_reporting(-1);
87892 $info = openssl_x509_parse(base64_decode('%s'));
87893 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
87894
87895 EOT;
87896 $script = '<'."?php\n".sprintf($script, $cert);
87897
87898 try {
87899 $process = new PhpProcess($script);
87900 $process->mustRun();
87901 } catch (\Exception $e) {
87902
87903
87904 return self::$useOpensslParse = false;
87905 }
87906
87907 $output = preg_split('{\r?\n}', trim($process->getOutput()));
87908 $errorOutput = trim($process->getErrorOutput());
87909
87910 if (
87911 is_array($output)
87912 && count($output) === 3
87913 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
87914 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
87915 && $output[2] === 'int(-1)'
87916 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
87917 ) {
87918
87919 return self::$useOpensslParse = true;
87920 }
87921
87922 return self::$useOpensslParse = false;
87923 }
87924
87925
87926
87927
87928
87929 public static function reset()
87930 {
87931 self::$caFileValidity = array();
87932 self::$caPath = null;
87933 self::$useOpensslParse = null;
87934 }
87935
87936
87937
87938
87939
87940 private static function getEnvVariable($name)
87941 {
87942 if (isset($_SERVER[$name])) {
87943 return (string) $_SERVER[$name];
87944 }
87945
87946 if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
87947 return (string) $value;
87948 }
87949
87950 return false;
87951 }
87952
87953
87954
87955
87956
87957
87958 private static function caFileUsable($certFile, LoggerInterface $logger = null)
87959 {
87960 return $certFile
87961 && static::isFile($certFile, $logger)
87962 && static::isReadable($certFile, $logger)
87963 && static::validateCaFile($certFile, $logger);
87964 }
87965
87966
87967
87968
87969
87970
87971 private static function caDirUsable($certDir, LoggerInterface $logger = null)
87972 {
87973 return $certDir
87974 && static::isDir($certDir, $logger)
87975 && static::isReadable($certDir, $logger)
87976 && static::glob($certDir . '/*', $logger);
87977 }
87978
87979
87980
87981
87982
87983
87984 private static function isFile($certFile, LoggerInterface $logger = null)
87985 {
87986 $isFile = @is_file($certFile);
87987 if (!$isFile && $logger) {
87988 $logger->debug(sprintf('Checked CA file %s does not exist or it is not a file.', $certFile));
87989 }
87990
87991 return $isFile;
87992 }
87993
87994
87995
87996
87997
87998
87999 private static function isDir($certDir, LoggerInterface $logger = null)
88000 {
88001 $isDir = @is_dir($certDir);
88002 if (!$isDir && $logger) {
88003 $logger->debug(sprintf('Checked directory %s does not exist or it is not a directory.', $certDir));
88004 }
88005
88006 return $isDir;
88007 }
88008
88009
88010
88011
88012
88013
88014 private static function isReadable($certFileOrDir, LoggerInterface $logger = null)
88015 {
88016 $isReadable = @is_readable($certFileOrDir);
88017 if (!$isReadable && $logger) {
88018 $logger->debug(sprintf('Checked file or directory %s is not readable.', $certFileOrDir));
88019 }
88020
88021 return $isReadable;
88022 }
88023
88024
88025
88026
88027
88028
88029 private static function glob($pattern, LoggerInterface $logger = null)
88030 {
88031 $certs = glob($pattern);
88032 if ($certs === false) {
88033 if ($logger) {
88034 $logger->debug(sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern));
88035 }
88036 return false;
88037 }
88038
88039 if (count($certs) === 0) {
88040 if ($logger) {
88041 $logger->debug(sprintf("No CA files found for pattern: %s", $pattern));
88042 }
88043 return false;
88044 }
88045
88046 return true;
88047 }
88048 }
88049 MIT License
88050
88051 Copyright (c) 2017 Composer
88052
88053 Permission is hereby granted, free of charge, to any person obtaining a copy
88054 of this software and associated documentation files (the "Software"), to deal
88055 in the Software without restriction, including without limitation the rights
88056 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88057 copies of the Software, and to permit persons to whom the Software is
88058 furnished to do so, subject to the following conditions:
88059
88060 The above copyright notice and this permission notice shall be included in all
88061 copies or substantial portions of the Software.
88062
88063 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
88064 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
88065 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
88066 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
88067 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
88068 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
88069 SOFTWARE.
88070 <?php
88071
88072
88073
88074
88075
88076
88077
88078
88079
88080
88081 namespace Composer\XdebugHandler;
88082
88083
88084
88085
88086 class PhpConfig
88087 {
88088
88089
88090
88091
88092
88093 public function useOriginal()
88094 {
88095 $this->getDataAndReset();
88096 return array();
88097 }
88098
88099
88100
88101
88102
88103
88104 public function useStandard()
88105 {
88106 if ($data = $this->getDataAndReset()) {
88107 return array('-n', '-c', $data['tmpIni']);
88108 }
88109
88110 return array();
88111 }
88112
88113
88114
88115
88116
88117
88118 public function usePersistent()
88119 {
88120 if ($data = $this->getDataAndReset()) {
88121 Process::setEnv('PHPRC', $data['tmpIni']);
88122 Process::setEnv('PHP_INI_SCAN_DIR', '');
88123 }
88124
88125 return array();
88126 }
88127
88128
88129
88130
88131
88132
88133 private function getDataAndReset()
88134 {
88135 if ($data = XdebugHandler::getRestartSettings()) {
88136 Process::setEnv('PHPRC', $data['phprc']);
88137 Process::setEnv('PHP_INI_SCAN_DIR', $data['scanDir']);
88138 }
88139
88140 return $data;
88141 }
88142 }
88143 <?php
88144
88145
88146
88147
88148
88149
88150
88151
88152
88153
88154 namespace Composer\XdebugHandler;
88155
88156
88157
88158
88159
88160
88161
88162
88163 class Process
88164 {
88165
88166
88167
88168
88169
88170
88171
88172
88173
88174
88175 public static function addColorOption(array $args, $colorOption)
88176 {
88177 if (!$colorOption
88178 || in_array($colorOption, $args)
88179 || !preg_match('/^--([a-z]+$)|(^--[a-z]+=)/', $colorOption, $matches)) {
88180 return $args;
88181 }
88182
88183 if (isset($matches[2])) {
88184
88185 if (false !== ($index = array_search($matches[2].'auto', $args))) {
88186 $args[$index] = $colorOption;
88187 return $args;
88188 } elseif (preg_grep('/^'.$matches[2].'/', $args)) {
88189 return $args;
88190 }
88191 } elseif (in_array('--no-'.$matches[1], $args)) {
88192 return $args;
88193 }
88194
88195
88196 if (false !== getenv('NO_COLOR')) {
88197 return $args;
88198 }
88199
88200 if (false !== ($index = array_search('--', $args))) {
88201
88202 array_splice($args, $index, 0, $colorOption);
88203 } else {
88204 $args[] = $colorOption;
88205 }
88206
88207 return $args;
88208 }
88209
88210
88211
88212
88213
88214
88215
88216
88217
88218
88219
88220
88221
88222 public static function escape($arg, $meta = true, $module = false)
88223 {
88224 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
88225 return "'".str_replace("'", "'\\''", $arg)."'";
88226 }
88227
88228 $quote = strpbrk($arg, " \t") !== false || $arg === '';
88229
88230 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
88231
88232 if ($meta) {
88233 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
88234
88235 if (!$meta) {
88236 $quote = $quote || strpbrk($arg, '^&|<>()') !== false;
88237 } elseif ($module && !$dquotes && $quote) {
88238 $meta = false;
88239 }
88240 }
88241
88242 if ($quote) {
88243 $arg = '"'.preg_replace('/(\\\\*)$/', '$1$1', $arg).'"';
88244 }
88245
88246 if ($meta) {
88247 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
88248 }
88249
88250 return $arg;
88251 }
88252
88253
88254
88255
88256
88257
88258
88259
88260
88261
88262
88263 public static function supportsColor($output)
88264 {
88265 if ('Hyper' === getenv('TERM_PROGRAM')) {
88266 return true;
88267 }
88268
88269 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
88270 return (function_exists('sapi_windows_vt100_support')
88271 && sapi_windows_vt100_support($output))
88272 || false !== getenv('ANSICON')
88273 || 'ON' === getenv('ConEmuANSI')
88274 || 'xterm' === getenv('TERM');
88275 }
88276
88277 if (function_exists('stream_isatty')) {
88278 return stream_isatty($output);
88279 }
88280
88281 if (function_exists('posix_isatty')) {
88282 return posix_isatty($output);
88283 }
88284
88285 $stat = fstat($output);
88286
88287 return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
88288 }
88289
88290
88291
88292
88293
88294
88295
88296
88297
88298 public static function setEnv($name, $value = false)
88299 {
88300 $unset = false === $value;
88301
88302 if (!putenv($unset ? $name : $name.'='.$value)) {
88303 return false;
88304 }
88305
88306 if ($unset) {
88307 unset($_SERVER[$name]);
88308 } else {
88309 $_SERVER[$name] = $value;
88310 }
88311
88312
88313 if (false !== stripos((string) ini_get('variables_order'), 'E')) {
88314 if ($unset) {
88315 unset($_ENV[$name]);
88316 } else {
88317 $_ENV[$name] = $value;
88318 }
88319 }
88320
88321 return true;
88322 }
88323 }
88324 <?php
88325
88326
88327
88328
88329
88330
88331
88332
88333
88334
88335 namespace Composer\XdebugHandler;
88336
88337 use Psr\Log\LoggerInterface;
88338 use Psr\Log\LogLevel;
88339
88340
88341
88342
88343
88344 class Status
88345 {
88346 const ENV_RESTART = 'XDEBUG_HANDLER_RESTART';
88347 const CHECK = 'Check';
88348 const ERROR = 'Error';
88349 const INFO = 'Info';
88350 const NORESTART = 'NoRestart';
88351 const RESTART = 'Restart';
88352 const RESTARTING = 'Restarting';
88353 const RESTARTED = 'Restarted';
88354
88355 private $debug;
88356 private $envAllowXdebug;
88357 private $loaded;
88358 private $logger;
88359 private $time;
88360
88361
88362
88363
88364
88365
88366
88367 public function __construct($envAllowXdebug, $debug)
88368 {
88369 $start = getenv(self::ENV_RESTART);
88370 Process::setEnv(self::ENV_RESTART);
88371 $this->time = $start ? round((microtime(true) - $start) * 1000) : 0;
88372
88373 $this->envAllowXdebug = $envAllowXdebug;
88374 $this->debug = $debug && defined('STDERR');
88375 }
88376
88377
88378
88379
88380 public function setLogger(LoggerInterface $logger)
88381 {
88382 $this->logger = $logger;
88383 }
88384
88385
88386
88387
88388
88389
88390
88391 public function report($op, $data)
88392 {
88393 if ($this->logger || $this->debug) {
88394 call_user_func(array($this, 'report'.$op), $data);
88395 }
88396 }
88397
88398
88399
88400
88401
88402
88403
88404 private function output($text, $level = null)
88405 {
88406 if ($this->logger) {
88407 $this->logger->log($level ?: LogLevel::DEBUG, $text);
88408 }
88409
88410 if ($this->debug) {
88411 fwrite(STDERR, sprintf('xdebug-handler[%d] %s', getmypid(), $text.PHP_EOL));
88412 }
88413 }
88414
88415 private function reportCheck($loaded)
88416 {
88417 $this->loaded = $loaded;
88418 $this->output('Checking '.$this->envAllowXdebug);
88419 }
88420
88421 private function reportError($error)
88422 {
88423 $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
88424 }
88425
88426 private function reportInfo($info)
88427 {
88428 $this->output($info);
88429 }
88430
88431 private function reportNoRestart()
88432 {
88433 $this->output($this->getLoadedMessage());
88434
88435 if ($this->loaded) {
88436 $text = sprintf('No restart (%s)', $this->getEnvAllow());
88437 if (!getenv($this->envAllowXdebug)) {
88438 $text .= ' Allowed by application';
88439 }
88440 $this->output($text);
88441 }
88442 }
88443
88444 private function reportRestart()
88445 {
88446 $this->output($this->getLoadedMessage());
88447 Process::setEnv(self::ENV_RESTART, (string) microtime(true));
88448 }
88449
88450 private function reportRestarted()
88451 {
88452 $loaded = $this->getLoadedMessage();
88453 $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded);
88454 $level = $this->loaded ? LogLevel::WARNING : null;
88455 $this->output($text, $level);
88456 }
88457
88458 private function reportRestarting($command)
88459 {
88460 $text = sprintf('Process restarting (%s)', $this->getEnvAllow());
88461 $this->output($text);
88462 $text = 'Running '.$command;
88463 $this->output($text);
88464 }
88465
88466
88467
88468
88469
88470
88471 private function getEnvAllow()
88472 {
88473 return $this->envAllowXdebug.'='.getenv($this->envAllowXdebug);
88474 }
88475
88476
88477
88478
88479
88480
88481 private function getLoadedMessage()
88482 {
88483 $loaded = $this->loaded ? sprintf('loaded (%s)', $this->loaded) : 'not loaded';
88484 return 'The Xdebug extension is '.$loaded;
88485 }
88486 }
88487 <?php
88488
88489
88490
88491
88492
88493
88494
88495
88496
88497
88498 namespace Composer\XdebugHandler;
88499
88500 use Psr\Log\LoggerInterface;
88501
88502
88503
88504
88505 class XdebugHandler
88506 {
88507 const SUFFIX_ALLOW = '_ALLOW_XDEBUG';
88508 const SUFFIX_INIS = '_ORIGINAL_INIS';
88509 const RESTART_ID = 'internal';
88510 const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS';
88511 const DEBUG = 'XDEBUG_HANDLER_DEBUG';
88512
88513
88514 protected $tmpIni;
88515
88516 private static $inRestart;
88517 private static $name;
88518 private static $skipped;
88519
88520 private $cli;
88521 private $colorOption;
88522 private $debug;
88523 private $envAllowXdebug;
88524 private $envOriginalInis;
88525 private $loaded;
88526 private $persistent;
88527 private $script;
88528
88529 private $statusWriter;
88530
88531
88532
88533
88534
88535
88536
88537
88538
88539
88540
88541
88542 public function __construct($envPrefix, $colorOption = '')
88543 {
88544 if (!is_string($envPrefix) || empty($envPrefix) || !is_string($colorOption)) {
88545 throw new \RuntimeException('Invalid constructor parameter');
88546 }
88547
88548 self::$name = strtoupper($envPrefix);
88549 $this->envAllowXdebug = self::$name.self::SUFFIX_ALLOW;
88550 $this->envOriginalInis = self::$name.self::SUFFIX_INIS;
88551
88552 $this->colorOption = $colorOption;
88553
88554 if (extension_loaded('xdebug')) {
88555 $ext = new \ReflectionExtension('xdebug');
88556 $this->loaded = $ext->getVersion() ?: 'unknown';
88557 }
88558
88559 if ($this->cli = PHP_SAPI === 'cli') {
88560 $this->debug = getenv(self::DEBUG);
88561 }
88562
88563 $this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug);
88564 }
88565
88566
88567
88568
88569
88570
88571
88572
88573 public function setLogger(LoggerInterface $logger)
88574 {
88575 $this->statusWriter->setLogger($logger);
88576 return $this;
88577 }
88578
88579
88580
88581
88582
88583
88584
88585
88586 public function setMainScript($script)
88587 {
88588 $this->script = $script;
88589 return $this;
88590 }
88591
88592
88593
88594
88595
88596
88597 public function setPersistent()
88598 {
88599 $this->persistent = true;
88600 return $this;
88601 }
88602
88603
88604
88605
88606
88607
88608
88609
88610 public function check()
88611 {
88612 $this->notify(Status::CHECK, $this->loaded);
88613 $envArgs = explode('|', (string) getenv($this->envAllowXdebug));
88614
88615 if (empty($envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) {
88616
88617 $this->notify(Status::RESTART);
88618
88619 if ($this->prepareRestart()) {
88620 $command = $this->getCommand();
88621 $this->restart($command);
88622 }
88623 return;
88624 }
88625
88626 if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
88627
88628 $this->notify(Status::RESTARTED);
88629
88630 Process::setEnv($this->envAllowXdebug);
88631 self::$inRestart = true;
88632
88633 if (!$this->loaded) {
88634
88635 self::$skipped = $envArgs[1];
88636 }
88637
88638 $this->tryEnableSignals();
88639
88640
88641 $this->setEnvRestartSettings($envArgs);
88642 return;
88643 }
88644
88645 $this->notify(Status::NORESTART);
88646
88647 if ($settings = self::getRestartSettings()) {
88648
88649 $this->syncSettings($settings);
88650 }
88651 }
88652
88653
88654
88655
88656
88657
88658
88659
88660
88661 public static function getAllIniFiles()
88662 {
88663 if (!empty(self::$name)) {
88664 $env = getenv(self::$name.self::SUFFIX_INIS);
88665
88666 if (false !== $env) {
88667 return explode(PATH_SEPARATOR, $env);
88668 }
88669 }
88670
88671 $paths = array((string) php_ini_loaded_file());
88672
88673 if ($scanned = php_ini_scanned_files()) {
88674 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
88675 }
88676
88677 return $paths;
88678 }
88679
88680
88681
88682
88683
88684
88685
88686
88687
88688 public static function getRestartSettings()
88689 {
88690 $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS));
88691
88692 if (count($envArgs) !== 6
88693 || (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) {
88694 return null;
88695 }
88696
88697 return array(
88698 'tmpIni' => $envArgs[0],
88699 'scannedInis' => (bool) $envArgs[1],
88700 'scanDir' => '*' === $envArgs[2] ? false : $envArgs[2],
88701 'phprc' => '*' === $envArgs[3] ? false : $envArgs[3],
88702 'inis' => explode(PATH_SEPARATOR, $envArgs[4]),
88703 'skipped' => $envArgs[5],
88704 );
88705 }
88706
88707
88708
88709
88710
88711
88712 public static function getSkippedVersion()
88713 {
88714 return (string) self::$skipped;
88715 }
88716
88717
88718
88719
88720
88721
88722
88723
88724 protected function requiresRestart($isLoaded)
88725 {
88726 return $isLoaded;
88727 }
88728
88729
88730
88731
88732
88733
88734 protected function restart($command)
88735 {
88736 $this->doRestart($command);
88737 }
88738
88739
88740
88741
88742
88743
88744 private function doRestart($command)
88745 {
88746 $this->tryEnableSignals();
88747 $this->notify(Status::RESTARTING, $command);
88748
88749
88750 if (function_exists('proc_open')) {
88751 if (defined('PHP_WINDOWS_VERSION_BUILD') && PHP_VERSION_ID < 80000) {
88752 $command = '"'.$command.'"';
88753 }
88754 $process = proc_open($command, array(), $pipes);
88755 if (is_resource($process)) {
88756 $exitCode = proc_close($process);
88757 }
88758 } else {
88759 passthru($command, $exitCode);
88760 }
88761
88762 if (!isset($exitCode)) {
88763
88764 $this->notify(Status::ERROR, 'Unable to restart process');
88765 $exitCode = -1;
88766 } else {
88767 $this->notify(Status::INFO, 'Restarted process exited '.$exitCode);
88768 }
88769
88770 if ($this->debug === '2') {
88771 $this->notify(Status::INFO, 'Temp ini saved: '.$this->tmpIni);
88772 } else {
88773 @unlink($this->tmpIni);
88774 }
88775
88776 exit($exitCode);
88777 }
88778
88779
88780
88781
88782
88783
88784
88785
88786
88787
88788
88789 private function prepareRestart()
88790 {
88791 $error = '';
88792 $iniFiles = self::getAllIniFiles();
88793 $scannedInis = count($iniFiles) > 1;
88794 $tmpDir = sys_get_temp_dir();
88795
88796 if (!$this->cli) {
88797 $error = 'Unsupported SAPI: '.PHP_SAPI;
88798 } elseif (!defined('PHP_BINARY')) {
88799 $error = 'PHP version is too old: '.PHP_VERSION;
88800 } elseif (!$this->checkConfiguration($info)) {
88801 $error = $info;
88802 } elseif (!$this->checkScanDirConfig()) {
88803 $error = 'PHP version does not report scanned inis: '.PHP_VERSION;
88804 } elseif (!$this->checkMainScript()) {
88805 $error = 'Unable to access main script: '.$this->script;
88806 } elseif (!$this->writeTmpIni($iniFiles, $tmpDir, $error)) {
88807 $error = $error ?: 'Unable to create temp ini file at: '.$tmpDir;
88808 } elseif (!$this->setEnvironment($scannedInis, $iniFiles)) {
88809 $error = 'Unable to set environment variables';
88810 }
88811
88812 if ($error) {
88813 $this->notify(Status::ERROR, $error);
88814 }
88815
88816 return empty($error);
88817 }
88818
88819
88820
88821
88822
88823
88824
88825
88826
88827
88828 private function writeTmpIni(array $iniFiles, $tmpDir, &$error)
88829 {
88830 if (!$this->tmpIni = @tempnam($tmpDir, '')) {
88831 return false;
88832 }
88833
88834
88835 if (empty($iniFiles[0])) {
88836 array_shift($iniFiles);
88837 }
88838
88839 $content = '';
88840 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
88841
88842 foreach ($iniFiles as $file) {
88843
88844 if (($data = @file_get_contents($file)) === false) {
88845 $error = 'Unable to read ini: '.$file;
88846 return false;
88847 }
88848 $content .= preg_replace($regex, ';$1', $data).PHP_EOL;
88849 }
88850
88851
88852 if ($config = parse_ini_string($content)) {
88853 $loaded = ini_get_all(null, false);
88854 $content .= $this->mergeLoadedConfig($loaded, $config);
88855 }
88856
88857
88858 $content .= 'opcache.enable_cli=0'.PHP_EOL;
88859
88860 return @file_put_contents($this->tmpIni, $content);
88861 }
88862
88863
88864
88865
88866
88867
88868 private function getCommand()
88869 {
88870 $php = array(PHP_BINARY);
88871 $args = array_slice($_SERVER['argv'], 1);
88872
88873 if (!$this->persistent) {
88874
88875 array_push($php, '-n', '-c', $this->tmpIni);
88876 }
88877
88878 if (defined('STDOUT') && Process::supportsColor(STDOUT)) {
88879 $args = Process::addColorOption($args, $this->colorOption);
88880 }
88881
88882 $args = array_merge($php, array($this->script), $args);
88883
88884 $cmd = Process::escape(array_shift($args), true, true);
88885 foreach ($args as $arg) {
88886 $cmd .= ' '.Process::escape($arg);
88887 }
88888
88889 return $cmd;
88890 }
88891
88892
88893
88894
88895
88896
88897
88898
88899
88900
88901
88902 private function setEnvironment($scannedInis, array $iniFiles)
88903 {
88904 $scanDir = getenv('PHP_INI_SCAN_DIR');
88905 $phprc = getenv('PHPRC');
88906
88907
88908 if (!putenv($this->envOriginalInis.'='.implode(PATH_SEPARATOR, $iniFiles))) {
88909 return false;
88910 }
88911
88912 if ($this->persistent) {
88913
88914 if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC='.$this->tmpIni)) {
88915 return false;
88916 }
88917 }
88918
88919
88920 $envArgs = array(
88921 self::RESTART_ID,
88922 $this->loaded,
88923 (int) $scannedInis,
88924 false === $scanDir ? '*' : $scanDir,
88925 false === $phprc ? '*' : $phprc,
88926 );
88927
88928 return putenv($this->envAllowXdebug.'='.implode('|', $envArgs));
88929 }
88930
88931
88932
88933
88934
88935
88936
88937 private function notify($op, $data = null)
88938 {
88939 $this->statusWriter->report($op, $data);
88940 }
88941
88942
88943
88944
88945
88946
88947
88948
88949
88950 private function mergeLoadedConfig(array $loadedConfig, array $iniConfig)
88951 {
88952 $content = '';
88953
88954 foreach ($loadedConfig as $name => $value) {
88955
88956 if (!is_string($value)
88957 || strpos($name, 'xdebug') === 0
88958 || $name === 'apc.mmap_file_mask') {
88959 continue;
88960 }
88961
88962 if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
88963
88964 $content .= $name.'="'.addcslashes($value, '\\"').'"'.PHP_EOL;
88965 }
88966 }
88967
88968 return $content;
88969 }
88970
88971
88972
88973
88974
88975
88976 private function checkMainScript()
88977 {
88978 if (null !== $this->script) {
88979
88980 return file_exists($this->script) || '--' === $this->script;
88981 }
88982
88983 if (file_exists($this->script = $_SERVER['argv'][0])) {
88984 return true;
88985 }
88986
88987
88988 $options = PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false;
88989 $trace = debug_backtrace($options);
88990
88991 if (($main = end($trace)) && isset($main['file'])) {
88992 return file_exists($this->script = $main['file']);
88993 }
88994
88995 return false;
88996 }
88997
88998
88999
89000
89001
89002
89003 private function setEnvRestartSettings($envArgs)
89004 {
89005 $settings = array(
89006 php_ini_loaded_file(),
89007 $envArgs[2],
89008 $envArgs[3],
89009 $envArgs[4],
89010 getenv($this->envOriginalInis),
89011 self::$skipped,
89012 );
89013
89014 Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings));
89015 }
89016
89017
89018
89019
89020
89021
89022 private function syncSettings(array $settings)
89023 {
89024 if (false === getenv($this->envOriginalInis)) {
89025
89026 Process::setEnv($this->envOriginalInis, implode(PATH_SEPARATOR, $settings['inis']));
89027 }
89028
89029 self::$skipped = $settings['skipped'];
89030 $this->notify(Status::INFO, 'Process called with existing restart settings');
89031 }
89032
89033
89034
89035
89036
89037
89038
89039
89040
89041 private function checkScanDirConfig()
89042 {
89043 return !(getenv('PHP_INI_SCAN_DIR')
89044 && !PHP_CONFIG_FILE_SCAN_DIR
89045 && (PHP_VERSION_ID < 70113
89046 || PHP_VERSION_ID === 70200));
89047 }
89048
89049
89050
89051
89052
89053
89054
89055 private function checkConfiguration(&$info)
89056 {
89057 if (!function_exists('proc_open') && !function_exists('passthru')) {
89058 $info = 'execution functions have been disabled (proc_open or passthru required)';
89059 return false;
89060 }
89061
89062 if (extension_loaded('uopz') && !ini_get('uopz.disable')) {
89063
89064 if (function_exists('uopz_allow_exit')) {
89065 @uopz_allow_exit(true);
89066 } else {
89067 $info = 'uopz extension is not compatible';
89068 return false;
89069 }
89070 }
89071
89072 return true;
89073 }
89074
89075
89076
89077
89078
89079
89080 private function tryEnableSignals()
89081 {
89082 if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
89083 pcntl_async_signals(true);
89084 $message = 'Async signals enabled';
89085
89086 if (!self::$inRestart) {
89087
89088 pcntl_signal(SIGINT, SIG_IGN);
89089 $message .= ' (SIGINT = SIG_IGN)';
89090 } elseif (is_int(pcntl_signal_get_handler(SIGINT))) {
89091
89092 pcntl_signal(SIGINT, SIG_DFL);
89093 $message .= ' (SIGINT = SIG_DFL)';
89094 }
89095 $this->notify(Status::INFO, $message);
89096 }
89097
89098 if (!self::$inRestart && function_exists('sapi_windows_set_ctrl_handler')) {
89099
89100
89101
89102 sapi_windows_set_ctrl_handler(function ($evt) {});
89103 $this->notify(Status::INFO, 'CTRL signals suppressed');
89104 }
89105 }
89106 }
89107 Copyright (c) 2012 PHP Framework Interoperability Group
89108
89109 Permission is hereby granted, free of charge, to any person obtaining a copy 
89110 of this software and associated documentation files (the "Software"), to deal
89111 in the Software without restriction, including without limitation the rights 
89112 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
89113 copies of the Software, and to permit persons to whom the Software is 
89114 furnished to do so, subject to the following conditions:
89115
89116 The above copyright notice and this permission notice shall be included in 
89117 all copies or substantial portions of the Software.
89118
89119 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
89120 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
89121 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
89122 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89123 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
89124 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
89125 THE SOFTWARE.
89126 <?php
89127
89128 namespace Psr\Log;
89129
89130
89131
89132
89133
89134
89135
89136
89137 abstract class AbstractLogger implements LoggerInterface
89138 {
89139
89140
89141
89142
89143
89144
89145
89146
89147 public function emergency($message, array $context = array())
89148 {
89149 $this->log(LogLevel::EMERGENCY, $message, $context);
89150 }
89151
89152
89153
89154
89155
89156
89157
89158
89159
89160
89161
89162
89163 public function alert($message, array $context = array())
89164 {
89165 $this->log(LogLevel::ALERT, $message, $context);
89166 }
89167
89168
89169
89170
89171
89172
89173
89174
89175
89176
89177
89178 public function critical($message, array $context = array())
89179 {
89180 $this->log(LogLevel::CRITICAL, $message, $context);
89181 }
89182
89183
89184
89185
89186
89187
89188
89189
89190
89191
89192 public function error($message, array $context = array())
89193 {
89194 $this->log(LogLevel::ERROR, $message, $context);
89195 }
89196
89197
89198
89199
89200
89201
89202
89203
89204
89205
89206
89207
89208 public function warning($message, array $context = array())
89209 {
89210 $this->log(LogLevel::WARNING, $message, $context);
89211 }
89212
89213
89214
89215
89216
89217
89218
89219
89220
89221 public function notice($message, array $context = array())
89222 {
89223 $this->log(LogLevel::NOTICE, $message, $context);
89224 }
89225
89226
89227
89228
89229
89230
89231
89232
89233
89234
89235
89236 public function info($message, array $context = array())
89237 {
89238 $this->log(LogLevel::INFO, $message, $context);
89239 }
89240
89241
89242
89243
89244
89245
89246
89247
89248
89249 public function debug($message, array $context = array())
89250 {
89251 $this->log(LogLevel::DEBUG, $message, $context);
89252 }
89253 }
89254 <?php
89255
89256 namespace Psr\Log;
89257
89258 class InvalidArgumentException extends \InvalidArgumentException
89259 {
89260 }
89261 <?php
89262
89263 namespace Psr\Log;
89264
89265
89266
89267
89268 class LogLevel
89269 {
89270 const EMERGENCY = 'emergency';
89271 const ALERT = 'alert';
89272 const CRITICAL = 'critical';
89273 const ERROR = 'error';
89274 const WARNING = 'warning';
89275 const NOTICE = 'notice';
89276 const INFO = 'info';
89277 const DEBUG = 'debug';
89278 }
89279 <?php
89280
89281 namespace Psr\Log;
89282
89283
89284
89285
89286 interface LoggerAwareInterface
89287 {
89288
89289
89290
89291
89292
89293
89294
89295 public function setLogger(LoggerInterface $logger);
89296 }
89297 <?php
89298
89299 namespace Psr\Log;
89300
89301
89302
89303
89304 trait LoggerAwareTrait
89305 {
89306
89307
89308
89309
89310
89311 protected $logger;
89312
89313
89314
89315
89316
89317
89318 public function setLogger(LoggerInterface $logger)
89319 {
89320 $this->logger = $logger;
89321 }
89322 }
89323 <?php
89324
89325 namespace Psr\Log;
89326
89327
89328
89329
89330
89331
89332
89333
89334
89335
89336
89337
89338
89339
89340
89341
89342 interface LoggerInterface
89343 {
89344
89345
89346
89347
89348
89349
89350
89351
89352 public function emergency($message, array $context = array());
89353
89354
89355
89356
89357
89358
89359
89360
89361
89362
89363
89364
89365 public function alert($message, array $context = array());
89366
89367
89368
89369
89370
89371
89372
89373
89374
89375
89376
89377 public function critical($message, array $context = array());
89378
89379
89380
89381
89382
89383
89384
89385
89386
89387
89388 public function error($message, array $context = array());
89389
89390
89391
89392
89393
89394
89395
89396
89397
89398
89399
89400
89401 public function warning($message, array $context = array());
89402
89403
89404
89405
89406
89407
89408
89409
89410
89411 public function notice($message, array $context = array());
89412
89413
89414
89415
89416
89417
89418
89419
89420
89421
89422
89423 public function info($message, array $context = array());
89424
89425
89426
89427
89428
89429
89430
89431
89432
89433 public function debug($message, array $context = array());
89434
89435
89436
89437
89438
89439
89440
89441
89442
89443
89444
89445
89446 public function log($level, $message, array $context = array());
89447 }
89448 <?php
89449
89450 namespace Psr\Log;
89451
89452
89453
89454
89455
89456
89457
89458
89459
89460 trait LoggerTrait
89461 {
89462
89463
89464
89465
89466
89467
89468
89469
89470 public function emergency($message, array $context = array())
89471 {
89472 $this->log(LogLevel::EMERGENCY, $message, $context);
89473 }
89474
89475
89476
89477
89478
89479
89480
89481
89482
89483
89484
89485
89486 public function alert($message, array $context = array())
89487 {
89488 $this->log(LogLevel::ALERT, $message, $context);
89489 }
89490
89491
89492
89493
89494
89495
89496
89497
89498
89499
89500
89501 public function critical($message, array $context = array())
89502 {
89503 $this->log(LogLevel::CRITICAL, $message, $context);
89504 }
89505
89506
89507
89508
89509
89510
89511
89512
89513
89514
89515 public function error($message, array $context = array())
89516 {
89517 $this->log(LogLevel::ERROR, $message, $context);
89518 }
89519
89520
89521
89522
89523
89524
89525
89526
89527
89528
89529
89530
89531 public function warning($message, array $context = array())
89532 {
89533 $this->log(LogLevel::WARNING, $message, $context);
89534 }
89535
89536
89537
89538
89539
89540
89541
89542
89543
89544 public function notice($message, array $context = array())
89545 {
89546 $this->log(LogLevel::NOTICE, $message, $context);
89547 }
89548
89549
89550
89551
89552
89553
89554
89555
89556
89557
89558
89559 public function info($message, array $context = array())
89560 {
89561 $this->log(LogLevel::INFO, $message, $context);
89562 }
89563
89564
89565
89566
89567
89568
89569
89570
89571
89572 public function debug($message, array $context = array())
89573 {
89574 $this->log(LogLevel::DEBUG, $message, $context);
89575 }
89576
89577
89578
89579
89580
89581
89582
89583
89584
89585
89586
89587
89588 abstract public function log($level, $message, array $context = array());
89589 }
89590 <?php
89591
89592 namespace Psr\Log;
89593
89594
89595
89596
89597
89598
89599
89600
89601
89602 class NullLogger extends AbstractLogger
89603 {
89604
89605
89606
89607
89608
89609
89610
89611
89612
89613
89614
89615 public function log($level, $message, array $context = array())
89616 {
89617
89618 }
89619 }
89620 <?php
89621
89622 namespace Psr\Log\Test;
89623
89624
89625
89626
89627
89628
89629
89630
89631 class DummyTest
89632 {
89633 public function __toString()
89634 {
89635 return 'DummyTest';
89636 }
89637 }
89638 <?php
89639
89640 namespace Psr\Log\Test;
89641
89642 use Psr\Log\LoggerInterface;
89643 use Psr\Log\LogLevel;
89644 use PHPUnit\Framework\TestCase;
89645
89646
89647
89648
89649
89650
89651
89652 abstract class LoggerInterfaceTest extends TestCase
89653 {
89654
89655
89656
89657 abstract public function getLogger();
89658
89659
89660
89661
89662
89663
89664
89665
89666
89667
89668 abstract public function getLogs();
89669
89670 public function testImplements()
89671 {
89672 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
89673 }
89674
89675
89676
89677
89678 public function testLogsAtAllLevels($level, $message)
89679 {
89680 $logger = $this->getLogger();
89681 $logger->{$level}($message, array('user' => 'Bob'));
89682 $logger->log($level, $message, array('user' => 'Bob'));
89683
89684 $expected = array(
89685 $level.' message of level '.$level.' with context: Bob',
89686 $level.' message of level '.$level.' with context: Bob',
89687 );
89688 $this->assertEquals($expected, $this->getLogs());
89689 }
89690
89691 public function provideLevelsAndMessages()
89692 {
89693 return array(
89694 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
89695 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
89696 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
89697 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
89698 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
89699 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
89700 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
89701 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
89702 );
89703 }
89704
89705
89706
89707
89708 public function testThrowsOnInvalidLevel()
89709 {
89710 $logger = $this->getLogger();
89711 $logger->log('invalid level', 'Foo');
89712 }
89713
89714 public function testContextReplacement()
89715 {
89716 $logger = $this->getLogger();
89717 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
89718
89719 $expected = array('info {Message {nothing} Bob Bar a}');
89720 $this->assertEquals($expected, $this->getLogs());
89721 }
89722
89723 public function testObjectCastToString()
89724 {
89725 if (method_exists($this, 'createPartialMock')) {
89726 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
89727 } else {
89728 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
89729 }
89730 $dummy->expects($this->once())
89731 ->method('__toString')
89732 ->will($this->returnValue('DUMMY'));
89733
89734 $this->getLogger()->warning($dummy);
89735
89736 $expected = array('warning DUMMY');
89737 $this->assertEquals($expected, $this->getLogs());
89738 }
89739
89740 public function testContextCanContainAnything()
89741 {
89742 $closed = fopen('php://memory', 'r');
89743 fclose($closed);
89744
89745 $context = array(
89746 'bool' => true,
89747 'null' => null,
89748 'string' => 'Foo',
89749 'int' => 0,
89750 'float' => 0.5,
89751 'nested' => array('with object' => new DummyTest),
89752 'object' => new \DateTime,
89753 'resource' => fopen('php://memory', 'r'),
89754 'closed' => $closed,
89755 );
89756
89757 $this->getLogger()->warning('Crazy context data', $context);
89758
89759 $expected = array('warning Crazy context data');
89760 $this->assertEquals($expected, $this->getLogs());
89761 }
89762
89763 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
89764 {
89765 $logger = $this->getLogger();
89766 $logger->warning('Random message', array('exception' => 'oops'));
89767 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
89768
89769 $expected = array(
89770 'warning Random message',
89771 'critical Uncaught Exception!'
89772 );
89773 $this->assertEquals($expected, $this->getLogs());
89774 }
89775 }
89776 <?php
89777
89778 namespace Psr\Log\Test;
89779
89780 use Psr\Log\AbstractLogger;
89781
89782
89783
89784
89785
89786
89787
89788
89789
89790
89791
89792
89793
89794
89795
89796
89797
89798
89799
89800
89801
89802
89803
89804
89805
89806
89807
89808
89809
89810
89811
89812
89813
89814
89815
89816
89817
89818
89819
89820
89821
89822
89823
89824
89825
89826
89827
89828
89829
89830
89831
89832 class TestLogger extends AbstractLogger
89833 {
89834
89835
89836
89837 public $records = [];
89838
89839 public $recordsByLevel = [];
89840
89841
89842
89843
89844 public function log($level, $message, array $context = [])
89845 {
89846 $record = [
89847 'level' => $level,
89848 'message' => $message,
89849 'context' => $context,
89850 ];
89851
89852 $this->recordsByLevel[$record['level']][] = $record;
89853 $this->records[] = $record;
89854 }
89855
89856 public function hasRecords($level)
89857 {
89858 return isset($this->recordsByLevel[$level]);
89859 }
89860
89861 public function hasRecord($record, $level)
89862 {
89863 if (is_string($record)) {
89864 $record = ['message' => $record];
89865 }
89866 return $this->hasRecordThatPasses(function ($rec) use ($record) {
89867 if ($rec['message'] !== $record['message']) {
89868 return false;
89869 }
89870 if (isset($record['context']) && $rec['context'] !== $record['context']) {
89871 return false;
89872 }
89873 return true;
89874 }, $level);
89875 }
89876
89877 public function hasRecordThatContains($message, $level)
89878 {
89879 return $this->hasRecordThatPasses(function ($rec) use ($message) {
89880 return strpos($rec['message'], $message) !== false;
89881 }, $level);
89882 }
89883
89884 public function hasRecordThatMatches($regex, $level)
89885 {
89886 return $this->hasRecordThatPasses(function ($rec) use ($regex) {
89887 return preg_match($regex, $rec['message']) > 0;
89888 }, $level);
89889 }
89890
89891 public function hasRecordThatPasses(callable $predicate, $level)
89892 {
89893 if (!isset($this->recordsByLevel[$level])) {
89894 return false;
89895 }
89896 foreach ($this->recordsByLevel[$level] as $i => $rec) {
89897 if (call_user_func($predicate, $rec, $i)) {
89898 return true;
89899 }
89900 }
89901 return false;
89902 }
89903
89904 public function __call($method, $args)
89905 {
89906 if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
89907 $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
89908 $level = strtolower($matches[2]);
89909 if (method_exists($this, $genericMethod)) {
89910 $args[] = $level;
89911 return call_user_func_array([$this, $genericMethod], $args);
89912 }
89913 }
89914 throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
89915 }
89916
89917 public function reset()
89918 {
89919 $this->records = [];
89920 $this->recordsByLevel = [];
89921 }
89922 }
89923 <?php
89924
89925
89926
89927 require_once __DIR__ . '/composer/autoload_real.php';
89928
89929 return ComposerAutoloaderInitComposerPhar1649860796::getLoader();
89930 <?php
89931
89932
89933
89934 $vendorDir = dirname(dirname(__FILE__));
89935 $baseDir = dirname($vendorDir);
89936
89937 return array(
89938 );
89939 <?php
89940
89941
89942
89943 $vendorDir = dirname(dirname(__FILE__));
89944 $baseDir = dirname($vendorDir);
89945
89946 return array(
89947 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
89948 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
89949 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
89950 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
89951 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
89952 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
89953 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
89954 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
89955 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
89956 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
89957 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
89958 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
89959 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
89960 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
89961 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
89962 'Composer\\' => array($baseDir . '/src/Composer'),
89963 );
89964 <?php
89965
89966
89967
89968 $vendorDir = dirname(dirname(__FILE__));
89969 $baseDir = dirname($vendorDir);
89970
89971 return array(
89972 );
89973 <?php
89974
89975
89976
89977 $vendorDir = dirname(dirname(__FILE__));
89978 $baseDir = dirname($vendorDir);
89979
89980 return array(
89981 '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
89982 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
89983 );
89984 <?php
89985
89986
89987
89988 class ComposerAutoloaderInitComposerPhar1649860796
89989 {
89990 private static $loader;
89991
89992 public static function loadClassLoader($class)
89993 {
89994 if ('Composer\Autoload\ClassLoader' === $class) {
89995 require __DIR__ . '/ClassLoader.php';
89996 }
89997 }
89998
89999
90000
90001
90002 public static function getLoader()
90003 {
90004 if (null !== self::$loader) {
90005 return self::$loader;
90006 }
90007
90008 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1649860796', 'loadClassLoader'), true, true);
90009 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
90010 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1649860796', 'loadClassLoader'));
90011
90012 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
90013 if ($useStaticLoader) {
90014 require_once __DIR__ . '/autoload_static.php';
90015
90016 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1649860796::getInitializer($loader));
90017 } else {
90018 $map = require __DIR__ . '/autoload_namespaces.php';
90019 foreach ($map as $namespace => $path) {
90020 $loader->set($namespace, $path);
90021 }
90022
90023 $map = require __DIR__ . '/autoload_psr4.php';
90024 foreach ($map as $namespace => $path) {
90025 $loader->setPsr4($namespace, $path);
90026 }
90027
90028 $classMap = require __DIR__ . '/autoload_classmap.php';
90029 if ($classMap) {
90030 $loader->addClassMap($classMap);
90031 }
90032 }
90033
90034 $loader->register(true);
90035
90036 if ($useStaticLoader) {
90037 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1649860796::$files;
90038 } else {
90039 $includeFiles = require __DIR__ . '/autoload_files.php';
90040 }
90041 foreach ($includeFiles as $fileIdentifier => $file) {
90042 composerRequireComposerPhar1649860796($fileIdentifier, $file);
90043 }
90044
90045 return $loader;
90046 }
90047 }
90048
90049 function composerRequireComposerPhar1649860796($fileIdentifier, $file)
90050 {
90051 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
90052 require $file;
90053
90054 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
90055 }
90056 }
90057 <?php
90058
90059
90060
90061 namespace Composer\Autoload;
90062
90063 class ComposerStaticInitComposerPhar1649860796
90064 {
90065 public static $files = array (
90066 '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
90067 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
90068 );
90069
90070 public static $prefixLengthsPsr4 = array (
90071 'S' => 
90072 array (
90073 'Symfony\\Polyfill\\Mbstring\\' => 26,
90074 'Symfony\\Polyfill\\Ctype\\' => 23,
90075 'Symfony\\Component\\Process\\' => 26,
90076 'Symfony\\Component\\Finder\\' => 25,
90077 'Symfony\\Component\\Filesystem\\' => 29,
90078 'Symfony\\Component\\Debug\\' => 24,
90079 'Symfony\\Component\\Console\\' => 26,
90080 'Seld\\PharUtils\\' => 15,
90081 'Seld\\JsonLint\\' => 14,
90082 ),
90083 'P' => 
90084 array (
90085 'Psr\\Log\\' => 8,
90086 ),
90087 'J' => 
90088 array (
90089 'JsonSchema\\' => 11,
90090 ),
90091 'C' => 
90092 array (
90093 'Composer\\XdebugHandler\\' => 23,
90094 'Composer\\Spdx\\' => 14,
90095 'Composer\\Semver\\' => 16,
90096 'Composer\\CaBundle\\' => 18,
90097 'Composer\\' => 9,
90098 ),
90099 );
90100
90101 public static $prefixDirsPsr4 = array (
90102 'Symfony\\Polyfill\\Mbstring\\' => 
90103 array (
90104 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
90105 ),
90106 'Symfony\\Polyfill\\Ctype\\' => 
90107 array (
90108 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
90109 ),
90110 'Symfony\\Component\\Process\\' => 
90111 array (
90112 0 => __DIR__ . '/..' . '/symfony/process',
90113 ),
90114 'Symfony\\Component\\Finder\\' => 
90115 array (
90116 0 => __DIR__ . '/..' . '/symfony/finder',
90117 ),
90118 'Symfony\\Component\\Filesystem\\' => 
90119 array (
90120 0 => __DIR__ . '/..' . '/symfony/filesystem',
90121 ),
90122 'Symfony\\Component\\Debug\\' => 
90123 array (
90124 0 => __DIR__ . '/..' . '/symfony/debug',
90125 ),
90126 'Symfony\\Component\\Console\\' => 
90127 array (
90128 0 => __DIR__ . '/..' . '/symfony/console',
90129 ),
90130 'Seld\\PharUtils\\' => 
90131 array (
90132 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
90133 ),
90134 'Seld\\JsonLint\\' => 
90135 array (
90136 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
90137 ),
90138 'Psr\\Log\\' => 
90139 array (
90140 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
90141 ),
90142 'JsonSchema\\' => 
90143 array (
90144 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
90145 ),
90146 'Composer\\XdebugHandler\\' => 
90147 array (
90148 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
90149 ),
90150 'Composer\\Spdx\\' => 
90151 array (
90152 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
90153 ),
90154 'Composer\\Semver\\' => 
90155 array (
90156 0 => __DIR__ . '/..' . '/composer/semver/src',
90157 ),
90158 'Composer\\CaBundle\\' => 
90159 array (
90160 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
90161 ),
90162 'Composer\\' => 
90163 array (
90164 0 => __DIR__ . '/../..' . '/src/Composer',
90165 ),
90166 );
90167
90168 public static function getInitializer(ClassLoader $loader)
90169 {
90170 return \Closure::bind(function () use ($loader) {
90171 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1649860796::$prefixLengthsPsr4;
90172 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1649860796::$prefixDirsPsr4;
90173
90174 }, null, ClassLoader::class);
90175 }
90176 }
90177 <?php
90178
90179
90180
90181
90182
90183
90184
90185
90186
90187
90188
90189 namespace Composer\Autoload;
90190
90191
90192
90193
90194
90195
90196
90197
90198
90199
90200
90201
90202
90203
90204
90205
90206
90207
90208
90209
90210
90211
90212
90213
90214
90215
90216
90217
90218
90219 class ClassLoader
90220 {
90221
90222 private $prefixLengthsPsr4 = array();
90223 private $prefixDirsPsr4 = array();
90224 private $fallbackDirsPsr4 = array();
90225
90226
90227 private $prefixesPsr0 = array();
90228 private $fallbackDirsPsr0 = array();
90229
90230 private $useIncludePath = false;
90231 private $classMap = array();
90232 private $classMapAuthoritative = false;
90233 private $missingClasses = array();
90234 private $apcuPrefix;
90235
90236 public function getPrefixes()
90237 {
90238 if (!empty($this->prefixesPsr0)) {
90239 return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
90240 }
90241
90242 return array();
90243 }
90244
90245 public function getPrefixesPsr4()
90246 {
90247 return $this->prefixDirsPsr4;
90248 }
90249
90250 public function getFallbackDirs()
90251 {
90252 return $this->fallbackDirsPsr0;
90253 }
90254
90255 public function getFallbackDirsPsr4()
90256 {
90257 return $this->fallbackDirsPsr4;
90258 }
90259
90260 public function getClassMap()
90261 {
90262 return $this->classMap;
90263 }
90264
90265
90266
90267
90268 public function addClassMap(array $classMap)
90269 {
90270 if ($this->classMap) {
90271 $this->classMap = array_merge($this->classMap, $classMap);
90272 } else {
90273 $this->classMap = $classMap;
90274 }
90275 }
90276
90277
90278
90279
90280
90281
90282
90283
90284
90285 public function add($prefix, $paths, $prepend = false)
90286 {
90287 if (!$prefix) {
90288 if ($prepend) {
90289 $this->fallbackDirsPsr0 = array_merge(
90290 (array) $paths,
90291 $this->fallbackDirsPsr0
90292 );
90293 } else {
90294 $this->fallbackDirsPsr0 = array_merge(
90295 $this->fallbackDirsPsr0,
90296 (array) $paths
90297 );
90298 }
90299
90300 return;
90301 }
90302
90303 $first = $prefix[0];
90304 if (!isset($this->prefixesPsr0[$first][$prefix])) {
90305 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
90306
90307 return;
90308 }
90309 if ($prepend) {
90310 $this->prefixesPsr0[$first][$prefix] = array_merge(
90311 (array) $paths,
90312 $this->prefixesPsr0[$first][$prefix]
90313 );
90314 } else {
90315 $this->prefixesPsr0[$first][$prefix] = array_merge(
90316 $this->prefixesPsr0[$first][$prefix],
90317 (array) $paths
90318 );
90319 }
90320 }
90321
90322
90323
90324
90325
90326
90327
90328
90329
90330
90331
90332 public function addPsr4($prefix, $paths, $prepend = false)
90333 {
90334 if (!$prefix) {
90335
90336 if ($prepend) {
90337 $this->fallbackDirsPsr4 = array_merge(
90338 (array) $paths,
90339 $this->fallbackDirsPsr4
90340 );
90341 } else {
90342 $this->fallbackDirsPsr4 = array_merge(
90343 $this->fallbackDirsPsr4,
90344 (array) $paths
90345 );
90346 }
90347 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
90348
90349 $length = strlen($prefix);
90350 if ('\\' !== $prefix[$length - 1]) {
90351 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
90352 }
90353 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
90354 $this->prefixDirsPsr4[$prefix] = (array) $paths;
90355 } elseif ($prepend) {
90356
90357 $this->prefixDirsPsr4[$prefix] = array_merge(
90358 (array) $paths,
90359 $this->prefixDirsPsr4[$prefix]
90360 );
90361 } else {
90362
90363 $this->prefixDirsPsr4[$prefix] = array_merge(
90364 $this->prefixDirsPsr4[$prefix],
90365 (array) $paths
90366 );
90367 }
90368 }
90369
90370
90371
90372
90373
90374
90375
90376
90377 public function set($prefix, $paths)
90378 {
90379 if (!$prefix) {
90380 $this->fallbackDirsPsr0 = (array) $paths;
90381 } else {
90382 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
90383 }
90384 }
90385
90386
90387
90388
90389
90390
90391
90392
90393
90394
90395 public function setPsr4($prefix, $paths)
90396 {
90397 if (!$prefix) {
90398 $this->fallbackDirsPsr4 = (array) $paths;
90399 } else {
90400 $length = strlen($prefix);
90401 if ('\\' !== $prefix[$length - 1]) {
90402 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
90403 }
90404 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
90405 $this->prefixDirsPsr4[$prefix] = (array) $paths;
90406 }
90407 }
90408
90409
90410
90411
90412
90413
90414 public function setUseIncludePath($useIncludePath)
90415 {
90416 $this->useIncludePath = $useIncludePath;
90417 }
90418
90419
90420
90421
90422
90423
90424
90425 public function getUseIncludePath()
90426 {
90427 return $this->useIncludePath;
90428 }
90429
90430
90431
90432
90433
90434
90435
90436 public function setClassMapAuthoritative($classMapAuthoritative)
90437 {
90438 $this->classMapAuthoritative = $classMapAuthoritative;
90439 }
90440
90441
90442
90443
90444
90445
90446 public function isClassMapAuthoritative()
90447 {
90448 return $this->classMapAuthoritative;
90449 }
90450
90451
90452
90453
90454
90455
90456 public function setApcuPrefix($apcuPrefix)
90457 {
90458 $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
90459 }
90460
90461
90462
90463
90464
90465
90466 public function getApcuPrefix()
90467 {
90468 return $this->apcuPrefix;
90469 }
90470
90471
90472
90473
90474
90475
90476 public function register($prepend = false)
90477 {
90478 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
90479 }
90480
90481
90482
90483
90484 public function unregister()
90485 {
90486 spl_autoload_unregister(array($this, 'loadClass'));
90487 }
90488
90489
90490
90491
90492
90493
90494
90495 public function loadClass($class)
90496 {
90497 if ($file = $this->findFile($class)) {
90498 includeFile($file);
90499
90500 return true;
90501 }
90502 }
90503
90504
90505
90506
90507
90508
90509
90510
90511 public function findFile($class)
90512 {
90513
90514 if (isset($this->classMap[$class])) {
90515 return $this->classMap[$class];
90516 }
90517 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
90518 return false;
90519 }
90520 if (null !== $this->apcuPrefix) {
90521 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
90522 if ($hit) {
90523 return $file;
90524 }
90525 }
90526
90527 $file = $this->findFileWithExtension($class, '.php');
90528
90529
90530 if (false === $file && defined('HHVM_VERSION')) {
90531 $file = $this->findFileWithExtension($class, '.hh');
90532 }
90533
90534 if (null !== $this->apcuPrefix) {
90535 apcu_add($this->apcuPrefix.$class, $file);
90536 }
90537
90538 if (false === $file) {
90539
90540 $this->missingClasses[$class] = true;
90541 }
90542
90543 return $file;
90544 }
90545
90546 private function findFileWithExtension($class, $ext)
90547 {
90548
90549 $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
90550
90551 $first = $class[0];
90552 if (isset($this->prefixLengthsPsr4[$first])) {
90553 $subPath = $class;
90554 while (false !== $lastPos = strrpos($subPath, '\\')) {
90555 $subPath = substr($subPath, 0, $lastPos);
90556 $search = $subPath . '\\';
90557 if (isset($this->prefixDirsPsr4[$search])) {
90558 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
90559 foreach ($this->prefixDirsPsr4[$search] as $dir) {
90560 if (file_exists($file = $dir . $pathEnd)) {
90561 return $file;
90562 }
90563 }
90564 }
90565 }
90566 }
90567
90568
90569 foreach ($this->fallbackDirsPsr4 as $dir) {
90570 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
90571 return $file;
90572 }
90573 }
90574
90575
90576 if (false !== $pos = strrpos($class, '\\')) {
90577
90578 $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
90579 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
90580 } else {
90581
90582 $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
90583 }
90584
90585 if (isset($this->prefixesPsr0[$first])) {
90586 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
90587 if (0 === strpos($class, $prefix)) {
90588 foreach ($dirs as $dir) {
90589 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
90590 return $file;
90591 }
90592 }
90593 }
90594 }
90595 }
90596
90597
90598 foreach ($this->fallbackDirsPsr0 as $dir) {
90599 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
90600 return $file;
90601 }
90602 }
90603
90604
90605 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
90606 return $file;
90607 }
90608
90609 return false;
90610 }
90611 }
90612
90613
90614
90615
90616
90617
90618 function includeFile($file)
90619 {
90620 include $file;
90621 }
90622 ##
90623 ## Bundle of CA Root Certificates
90624 ##
90625 ## Certificate data from Mozilla as of: Tue Oct 26 03:12:05 2021 GMT
90626 ##
90627 ## This is a bundle of X.509 certificates of public Certificate Authorities
90628 ## (CA). These were automatically extracted from Mozilla's root certificates
90629 ## file (certdata.txt).  This file can be found in the mozilla source tree:
90630 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
90631 ##
90632 ## It contains the certificates in PEM format and therefore
90633 ## can be directly used with curl / libcurl / php_curl, or with
90634 ## an Apache+mod_ssl webserver for SSL client authentication.
90635 ## Just configure this file as the SSLCACertificateFile.
90636 ##
90637 ## Conversion done with mk-ca-bundle.pl version 1.28.
90638 ## SHA256: bb36818a81feaa4cca61101e6d6276cd09e972efcb08112dfed846918ca41d7f
90639 ##
90640
90641
90642 GlobalSign Root CA
90643 ==================
90644 -----BEGIN CERTIFICATE-----
90645 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
90646 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
90647 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
90648 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
90649 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
90650 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
90651 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
90652 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
90653 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
90654 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
90655 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
90656 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
90657 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
90658 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
90659 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
90660 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
90661 -----END CERTIFICATE-----
90662
90663 GlobalSign Root CA - R2
90664 =======================
90665 -----BEGIN CERTIFICATE-----
90666 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
90667 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
90668 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
90669 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
90670 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
90671 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
90672 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
90673 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
90674 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
90675 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
90676 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
90677 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
90678 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
90679 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
90680 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
90681 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
90682 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
90683 -----END CERTIFICATE-----
90684
90685 Entrust.net Premium 2048 Secure Server CA
90686 =========================================
90687 -----BEGIN CERTIFICATE-----
90688 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
90689 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
90690 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
90691 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
90692 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
90693 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
90694 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
90695 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
90696 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
90697 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
90698 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
90699 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
90700 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
90701 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
90702 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
90703 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
90704 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
90705 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
90706 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
90707 -----END CERTIFICATE-----
90708
90709 Baltimore CyberTrust Root
90710 =========================
90711 -----BEGIN CERTIFICATE-----
90712 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
90713 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
90714 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
90715 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
90716 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
90717 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
90718 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
90719 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
90720 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
90721 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
90722 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
90723 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
90724 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
90725 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
90726 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
90727 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
90728 -----END CERTIFICATE-----
90729
90730 Entrust Root Certification Authority
90731 ====================================
90732 -----BEGIN CERTIFICATE-----
90733 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
90734 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
90735 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
90736 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
90737 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
90738 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
90739 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
90740 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
90741 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
90742 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
90743 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
90744 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
90745 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
90746 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
90747 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
90748 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
90749 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
90750 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
90751 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
90752 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
90753 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
90754 -----END CERTIFICATE-----
90755
90756 Comodo AAA Services root
90757 ========================
90758 -----BEGIN CERTIFICATE-----
90759 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
90760 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
90761 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
90762 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
90763 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
90764 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
90765 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
90766 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
90767 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
90768 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
90769 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
90770 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
90771 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
90772 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
90773 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
90774 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
90775 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
90776 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
90777 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
90778 -----END CERTIFICATE-----
90779
90780 QuoVadis Root CA 2
90781 ==================
90782 -----BEGIN CERTIFICATE-----
90783 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
90784 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
90785 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
90786 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
90787 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
90788 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
90789 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
90790 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
90791 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
90792 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
90793 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
90794 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
90795 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
90796 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
90797 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
90798 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
90799 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
90800 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
90801 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
90802 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
90803 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
90804 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
90805 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
90806 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
90807 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
90808 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
90809 -----END CERTIFICATE-----
90810
90811 QuoVadis Root CA 3
90812 ==================
90813 -----BEGIN CERTIFICATE-----
90814 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
90815 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
90816 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
90817 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
90818 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
90819 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
90820 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
90821 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
90822 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
90823 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
90824 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
90825 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
90826 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
90827 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
90828 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
90829 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
90830 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
90831 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
90832 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
90833 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
90834 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
90835 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
90836 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
90837 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
90838 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
90839 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
90840 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
90841 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
90842 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
90843 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
90844 -----END CERTIFICATE-----
90845
90846 Security Communication Root CA
90847 ==============================
90848 -----BEGIN CERTIFICATE-----
90849 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
90850 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
90851 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
90852 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
90853 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
90854 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
90855 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
90856 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
90857 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
90858 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
90859 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
90860 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
90861 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
90862 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
90863 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
90864 FL39vmwLAw==
90865 -----END CERTIFICATE-----
90866
90867 XRamp Global CA Root
90868 ====================
90869 -----BEGIN CERTIFICATE-----
90870 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
90871 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
90872 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
90873 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
90874 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
90875 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
90876 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
90877 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
90878 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
90879 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
90880 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
90881 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
90882 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
90883 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
90884 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
90885 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
90886 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
90887 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
90888 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
90889 -----END CERTIFICATE-----
90890
90891 Go Daddy Class 2 CA
90892 ===================
90893 -----BEGIN CERTIFICATE-----
90894 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
90895 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
90896 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
90897 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
90898 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
90899 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
90900 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
90901 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
90902 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
90903 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
90904 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
90905 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
90906 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
90907 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
90908 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
90909 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
90910 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
90911 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
90912 vZ8=
90913 -----END CERTIFICATE-----
90914
90915 Starfield Class 2 CA
90916 ====================
90917 -----BEGIN CERTIFICATE-----
90918 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
90919 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
90920 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
90921 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
90922 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
90923 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
90924 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
90925 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
90926 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
90927 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
90928 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
90929 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
90930 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
90931 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
90932 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
90933 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
90934 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
90935 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
90936 QBFGmh95DmK/D5fs4C8fF5Q=
90937 -----END CERTIFICATE-----
90938
90939 DigiCert Assured ID Root CA
90940 ===========================
90941 -----BEGIN CERTIFICATE-----
90942 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
90943 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
90944 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
90945 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
90946 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
90947 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
90948 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
90949 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
90950 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
90951 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
90952 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
90953 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
90954 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
90955 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
90956 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
90957 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
90958 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
90959 -----END CERTIFICATE-----
90960
90961 DigiCert Global Root CA
90962 =======================
90963 -----BEGIN CERTIFICATE-----
90964 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
90965 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
90966 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
90967 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
90968 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
90969 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
90970 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
90971 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
90972 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
90973 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
90974 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
90975 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
90976 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
90977 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
90978 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
90979 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
90980 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
90981 -----END CERTIFICATE-----
90982
90983 DigiCert High Assurance EV Root CA
90984 ==================================
90985 -----BEGIN CERTIFICATE-----
90986 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
90987 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
90988 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
90989 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
90990 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
90991 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
90992 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
90993 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
90994 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
90995 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
90996 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
90997 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
90998 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
90999 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
91000 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
91001 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
91002 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
91003 -----END CERTIFICATE-----
91004
91005 SwissSign Gold CA - G2
91006 ======================
91007 -----BEGIN CERTIFICATE-----
91008 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
91009 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
91010 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
91011 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
91012 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
91013 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
91014 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
91015 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
91016 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
91017 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
91018 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
91019 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
91020 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
91021 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
91022 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
91023 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
91024 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
91025 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
91026 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
91027 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
91028 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
91029 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
91030 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
91031 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
91032 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
91033 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
91034 -----END CERTIFICATE-----
91035
91036 SwissSign Silver CA - G2
91037 ========================
91038 -----BEGIN CERTIFICATE-----
91039 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
91040 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
91041 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
91042 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
91043 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
91044 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
91045 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
91046 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
91047 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
91048 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
91049 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
91050 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
91051 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
91052 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
91053 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
91054 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
91055 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
91056 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
91057 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
91058 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
91059 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
91060 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
91061 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
91062 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
91063 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
91064 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
91065 -----END CERTIFICATE-----
91066
91067 SecureTrust CA
91068 ==============
91069 -----BEGIN CERTIFICATE-----
91070 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
91071 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
91072 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
91073 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
91074 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
91075 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
91076 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
91077 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
91078 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
91079 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
91080 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
91081 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
91082 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
91083 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
91084 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
91085 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
91086 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
91087 -----END CERTIFICATE-----
91088
91089 Secure Global CA
91090 ================
91091 -----BEGIN CERTIFICATE-----
91092 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
91093 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
91094 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
91095 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
91096 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
91097 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
91098 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
91099 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
91100 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
91101 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
91102 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
91103 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
91104 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
91105 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
91106 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
91107 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
91108 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
91109 -----END CERTIFICATE-----
91110
91111 COMODO Certification Authority
91112 ==============================
91113 -----BEGIN CERTIFICATE-----
91114 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
91115 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
91116 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
91117 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
91118 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
91119 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
91120 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
91121 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
91122 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
91123 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
91124 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
91125 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
91126 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
91127 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
91128 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
91129 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
91130 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
91131 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
91132 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
91133 -----END CERTIFICATE-----
91134
91135 Network Solutions Certificate Authority
91136 =======================================
91137 -----BEGIN CERTIFICATE-----
91138 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
91139 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
91140 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
91141 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
91142 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
91143 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
91144 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
91145 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
91146 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
91147 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
91148 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
91149 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
91150 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
91151 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
91152 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
91153 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
91154 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
91155 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
91156 -----END CERTIFICATE-----
91157
91158 COMODO ECC Certification Authority
91159 ==================================
91160 -----BEGIN CERTIFICATE-----
91161 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
91162 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
91163 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
91164 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
91165 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
91166 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
91167 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
91168 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
91169 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
91170 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
91171 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
91172 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
91173 -----END CERTIFICATE-----
91174
91175 Certigna
91176 ========
91177 -----BEGIN CERTIFICATE-----
91178 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
91179 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
91180 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
91181 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
91182 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
91183 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
91184 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
91185 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
91186 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
91187 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
91188 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
91189 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
91190 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
91191 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
91192 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
91193 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
91194 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
91195 -----END CERTIFICATE-----
91196
91197 Cybertrust Global Root
91198 ======================
91199 -----BEGIN CERTIFICATE-----
91200 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
91201 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
91202 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
91203 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
91204 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
91205 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
91206 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
91207 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
91208 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
91209 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
91210 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
91211 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
91212 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
91213 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
91214 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
91215 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
91216 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
91217 -----END CERTIFICATE-----
91218
91219 ePKI Root Certification Authority
91220 =================================
91221 -----BEGIN CERTIFICATE-----
91222 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
91223 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
91224 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
91225 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
91226 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
91227 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
91228 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
91229 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
91230 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
91231 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
91232 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
91233 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
91234 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
91235 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
91236 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
91237 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
91238 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
91239 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
91240 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
91241 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
91242 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
91243 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
91244 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
91245 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
91246 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
91247 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
91248 -----END CERTIFICATE-----
91249
91250 certSIGN ROOT CA
91251 ================
91252 -----BEGIN CERTIFICATE-----
91253 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
91254 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
91255 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
91256 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
91257 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
91258 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
91259 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
91260 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
91261 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
91262 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
91263 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
91264 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
91265 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
91266 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
91267 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
91268 -----END CERTIFICATE-----
91269
91270 NetLock Arany (Class Gold) Főtanúsítvány
91271 ========================================
91272 -----BEGIN CERTIFICATE-----
91273 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
91274 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
91275 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
91276 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
91277 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
91278 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
91279 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
91280 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
91281 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
91282 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
91283 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
91284 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
91285 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
91286 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
91287 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
91288 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
91289 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
91290 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
91291 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
91292 -----END CERTIFICATE-----
91293
91294 Hongkong Post Root CA 1
91295 =======================
91296 -----BEGIN CERTIFICATE-----
91297 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
91298 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
91299 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
91300 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
91301 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
91302 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
91303 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
91304 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
91305 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
91306 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
91307 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
91308 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
91309 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
91310 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
91311 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
91312 -----END CERTIFICATE-----
91313
91314 SecureSign RootCA11
91315 ===================
91316 -----BEGIN CERTIFICATE-----
91317 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
91318 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
91319 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
91320 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
91321 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
91322 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
91323 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
91324 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
91325 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
91326 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
91327 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
91328 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
91329 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
91330 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
91331 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
91332 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
91333 -----END CERTIFICATE-----
91334
91335 Microsec e-Szigno Root CA 2009
91336 ==============================
91337 -----BEGIN CERTIFICATE-----
91338 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
91339 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
91340 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
91341 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
91342 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
91343 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
91344 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
91345 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
91346 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
91347 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
91348 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
91349 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
91350 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
91351 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
91352 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
91353 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
91354 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
91355 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
91356 LXpUq3DDfSJlgnCW
91357 -----END CERTIFICATE-----
91358
91359 GlobalSign Root CA - R3
91360 =======================
91361 -----BEGIN CERTIFICATE-----
91362 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
91363 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
91364 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
91365 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
91366 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
91367 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
91368 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
91369 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
91370 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
91371 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
91372 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
91373 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
91374 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
91375 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
91376 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
91377 kpeDMdmztcpHWD9f
91378 -----END CERTIFICATE-----
91379
91380 Autoridad de Certificacion Firmaprofesional CIF A62634068
91381 =========================================================
91382 -----BEGIN CERTIFICATE-----
91383 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
91384 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
91385 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
91386 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
91387 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
91388 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
91389 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
91390 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
91391 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
91392 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
91393 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
91394 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
91395 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
91396 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
91397 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
91398 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
91399 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
91400 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
91401 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
91402 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
91403 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
91404 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
91405 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
91406 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
91407 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
91408 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
91409 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
91410 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
91411 -----END CERTIFICATE-----
91412
91413 Izenpe.com
91414 ==========
91415 -----BEGIN CERTIFICATE-----
91416 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
91417 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
91418 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
91419 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
91420 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
91421 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
91422 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
91423 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
91424 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
91425 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
91426 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
91427 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
91428 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
91429 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
91430 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
91431 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
91432 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
91433 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
91434 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
91435 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
91436 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
91437 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
91438 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
91439 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
91440 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
91441 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
91442 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
91443 -----END CERTIFICATE-----
91444
91445 Go Daddy Root Certificate Authority - G2
91446 ========================================
91447 -----BEGIN CERTIFICATE-----
91448 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
91449 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
91450 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
91451 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
91452 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
91453 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
91454 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
91455 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
91456 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
91457 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
91458 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
91459 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
91460 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
91461 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
91462 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
91463 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
91464 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
91465 -----END CERTIFICATE-----
91466
91467 Starfield Root Certificate Authority - G2
91468 =========================================
91469 -----BEGIN CERTIFICATE-----
91470 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
91471 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
91472 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
91473 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
91474 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
91475 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
91476 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
91477 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
91478 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
91479 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
91480 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
91481 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
91482 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
91483 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
91484 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
91485 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
91486 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
91487 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
91488 -----END CERTIFICATE-----
91489
91490 Starfield Services Root Certificate Authority - G2
91491 ==================================================
91492 -----BEGIN CERTIFICATE-----
91493 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
91494 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
91495 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
91496 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
91497 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
91498 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
91499 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
91500 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
91501 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
91502 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
91503 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
91504 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
91505 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
91506 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
91507 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
91508 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
91509 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
91510 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
91511 -----END CERTIFICATE-----
91512
91513 AffirmTrust Commercial
91514 ======================
91515 -----BEGIN CERTIFICATE-----
91516 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
91517 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
91518 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
91519 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
91520 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
91521 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
91522 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
91523 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
91524 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
91525 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
91526 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
91527 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
91528 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
91529 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
91530 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
91531 -----END CERTIFICATE-----
91532
91533 AffirmTrust Networking
91534 ======================
91535 -----BEGIN CERTIFICATE-----
91536 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
91537 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
91538 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
91539 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
91540 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
91541 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
91542 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
91543 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
91544 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
91545 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
91546 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
91547 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
91548 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
91549 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
91550 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
91551 -----END CERTIFICATE-----
91552
91553 AffirmTrust Premium
91554 ===================
91555 -----BEGIN CERTIFICATE-----
91556 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
91557 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
91558 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
91559 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
91560 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
91561 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
91562 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
91563 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
91564 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
91565 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
91566 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
91567 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
91568 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
91569 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
91570 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
91571 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
91572 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
91573 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
91574 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
91575 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
91576 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
91577 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
91578 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
91579 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
91580 -----END CERTIFICATE-----
91581
91582 AffirmTrust Premium ECC
91583 =======================
91584 -----BEGIN CERTIFICATE-----
91585 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
91586 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
91587 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
91588 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
91589 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
91590 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
91591 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
91592 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
91593 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
91594 eQ==
91595 -----END CERTIFICATE-----
91596
91597 Certum Trusted Network CA
91598 =========================
91599 -----BEGIN CERTIFICATE-----
91600 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
91601 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
91602 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
91603 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
91604 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
91605 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
91606 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
91607 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
91608 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
91609 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
91610 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
91611 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
91612 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
91613 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
91614 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
91615 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
91616 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
91617 -----END CERTIFICATE-----
91618
91619 TWCA Root Certification Authority
91620 =================================
91621 -----BEGIN CERTIFICATE-----
91622 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
91623 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
91624 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
91625 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
91626 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
91627 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
91628 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
91629 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
91630 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
91631 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
91632 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
91633 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
91634 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
91635 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
91636 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
91637 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
91638 -----END CERTIFICATE-----
91639
91640 Security Communication RootCA2
91641 ==============================
91642 -----BEGIN CERTIFICATE-----
91643 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
91644 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
91645 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
91646 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
91647 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
91648 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
91649 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
91650 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
91651 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
91652 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
91653 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
91654 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
91655 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
91656 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
91657 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
91658 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
91659 -----END CERTIFICATE-----
91660
91661 EC-ACC
91662 ======
91663 -----BEGIN CERTIFICATE-----
91664 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
91665 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
91666 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
91667 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
91668 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
91669 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
91670 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
91671 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
91672 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
91673 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
91674 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
91675 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
91676 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
91677 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
91678 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
91679 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
91680 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
91681 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
91682 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
91683 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
91684 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
91685 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
91686 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
91687 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
91688 5EI=
91689 -----END CERTIFICATE-----
91690
91691 Hellenic Academic and Research Institutions RootCA 2011
91692 =======================================================
91693 -----BEGIN CERTIFICATE-----
91694 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
91695 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
91696 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
91697 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
91698 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
91699 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
91700 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
91701 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
91702 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
91703 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
91704 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
91705 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
91706 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
91707 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
91708 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
91709 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
91710 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
91711 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
91712 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
91713 -----END CERTIFICATE-----
91714
91715 Actalis Authentication Root CA
91716 ==============================
91717 -----BEGIN CERTIFICATE-----
91718 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
91719 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
91720 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
91721 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
91722 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
91723 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
91724 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
91725 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
91726 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
91727 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
91728 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
91729 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
91730 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
91731 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
91732 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
91733 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
91734 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
91735 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
91736 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
91737 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
91738 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
91739 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
91740 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
91741 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
91742 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
91743 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
91744 -----END CERTIFICATE-----
91745
91746 Buypass Class 2 Root CA
91747 =======================
91748 -----BEGIN CERTIFICATE-----
91749 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
91750 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
91751 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
91752 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
91753 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
91754 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
91755 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
91756 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
91757 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
91758 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
91759 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
91760 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
91761 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
91762 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
91763 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
91764 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
91765 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
91766 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
91767 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
91768 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
91769 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
91770 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
91771 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
91772 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
91773 rJgWVqA=
91774 -----END CERTIFICATE-----
91775
91776 Buypass Class 3 Root CA
91777 =======================
91778 -----BEGIN CERTIFICATE-----
91779 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
91780 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
91781 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
91782 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
91783 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
91784 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
91785 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
91786 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
91787 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
91788 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
91789 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
91790 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
91791 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
91792 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
91793 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
91794 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
91795 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
91796 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
91797 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
91798 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
91799 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
91800 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
91801 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
91802 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
91803 Cp/HuZc=
91804 -----END CERTIFICATE-----
91805
91806 T-TeleSec GlobalRoot Class 3
91807 ============================
91808 -----BEGIN CERTIFICATE-----
91809 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
91810 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
91811 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
91812 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
91813 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
91814 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
91815 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
91816 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
91817 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
91818 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
91819 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
91820 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
91821 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
91822 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
91823 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
91824 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
91825 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
91826 -----END CERTIFICATE-----
91827
91828 D-TRUST Root Class 3 CA 2 2009
91829 ==============================
91830 -----BEGIN CERTIFICATE-----
91831 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
91832 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
91833 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
91834 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
91835 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
91836 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
91837 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
91838 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
91839 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
91840 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
91841 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
91842 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
91843 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
91844 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
91845 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
91846 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
91847 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
91848 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
91849 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
91850 -----END CERTIFICATE-----
91851
91852 D-TRUST Root Class 3 CA 2 EV 2009
91853 =================================
91854 -----BEGIN CERTIFICATE-----
91855 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
91856 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
91857 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
91858 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
91859 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
91860 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
91861 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
91862 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
91863 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
91864 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
91865 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
91866 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
91867 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
91868 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
91869 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
91870 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
91871 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
91872 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
91873 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
91874 w9y4AyHqnxbxLFS1
91875 -----END CERTIFICATE-----
91876
91877 CA Disig Root R2
91878 ================
91879 -----BEGIN CERTIFICATE-----
91880 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
91881 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
91882 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
91883 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
91884 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
91885 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
91886 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
91887 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
91888 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
91889 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
91890 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
91891 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
91892 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
91893 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
91894 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
91895 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
91896 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
91897 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
91898 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
91899 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
91900 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
91901 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
91902 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
91903 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
91904 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
91905 -----END CERTIFICATE-----
91906
91907 ACCVRAIZ1
91908 =========
91909 -----BEGIN CERTIFICATE-----
91910 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
91911 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
91912 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
91913 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
91914 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
91915 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
91916 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
91917 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
91918 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
91919 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
91920 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
91921 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
91922 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
91923 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
91924 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
91925 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
91926 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
91927 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
91928 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
91929 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
91930 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
91931 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
91932 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
91933 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
91934 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
91935 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
91936 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
91937 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
91938 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
91939 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
91940 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
91941 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
91942 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
91943 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
91944 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
91945 EfbRD0tVNEYqi4Y7
91946 -----END CERTIFICATE-----
91947
91948 TWCA Global Root CA
91949 ===================
91950 -----BEGIN CERTIFICATE-----
91951 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
91952 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
91953 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
91954 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
91955 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
91956 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
91957 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
91958 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
91959 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
91960 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
91961 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
91962 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
91963 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
91964 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
91965 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
91966 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
91967 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
91968 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
91969 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
91970 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
91971 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
91972 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
91973 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
91974 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
91975 -----END CERTIFICATE-----
91976
91977 TeliaSonera Root CA v1
91978 ======================
91979 -----BEGIN CERTIFICATE-----
91980 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
91981 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
91982 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
91983 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
91984 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
91985 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
91986 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
91987 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
91988 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
91989 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
91990 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
91991 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
91992 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
91993 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
91994 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
91995 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
91996 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
91997 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
91998 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
91999 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
92000 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
92001 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
92002 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
92003 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
92004 -----END CERTIFICATE-----
92005
92006 E-Tugra Certification Authority
92007 ===============================
92008 -----BEGIN CERTIFICATE-----
92009 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
92010 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
92011 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
92012 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
92013 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
92014 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
92015 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
92016 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
92017 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
92018 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
92019 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
92020 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
92021 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
92022 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
92023 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
92024 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
92025 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
92026 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
92027 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
92028 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
92029 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
92030 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
92031 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
92032 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
92033 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
92034 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
92035 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
92036 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
92037 C7TbO6Orb1wdtn7os4I07QZcJA==
92038 -----END CERTIFICATE-----
92039
92040 T-TeleSec GlobalRoot Class 2
92041 ============================
92042 -----BEGIN CERTIFICATE-----
92043 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
92044 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
92045 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
92046 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
92047 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
92048 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
92049 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
92050 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
92051 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
92052 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
92053 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
92054 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
92055 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
92056 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
92057 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
92058 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
92059 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
92060 -----END CERTIFICATE-----
92061
92062 Atos TrustedRoot 2011
92063 =====================
92064 -----BEGIN CERTIFICATE-----
92065 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
92066 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
92067 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
92068 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
92069 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
92070 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
92071 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
92072 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
92073 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
92074 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
92075 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
92076 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
92077 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
92078 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
92079 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
92080 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
92081 -----END CERTIFICATE-----
92082
92083 QuoVadis Root CA 1 G3
92084 =====================
92085 -----BEGIN CERTIFICATE-----
92086 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
92087 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
92088 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
92089 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
92090 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
92091 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
92092 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
92093 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
92094 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
92095 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
92096 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
92097 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
92098 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
92099 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
92100 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
92101 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
92102 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
92103 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
92104 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
92105 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
92106 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
92107 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
92108 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
92109 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
92110 hMJKzRwuJIczYOXD
92111 -----END CERTIFICATE-----
92112
92113 QuoVadis Root CA 2 G3
92114 =====================
92115 -----BEGIN CERTIFICATE-----
92116 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
92117 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
92118 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
92119 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
92120 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
92121 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
92122 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
92123 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
92124 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
92125 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
92126 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
92127 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
92128 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
92129 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
92130 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
92131 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
92132 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
92133 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
92134 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
92135 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
92136 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
92137 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
92138 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
92139 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
92140 O3jtZsSOeWmD3n+M
92141 -----END CERTIFICATE-----
92142
92143 QuoVadis Root CA 3 G3
92144 =====================
92145 -----BEGIN CERTIFICATE-----
92146 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
92147 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
92148 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
92149 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
92150 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
92151 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
92152 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
92153 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
92154 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
92155 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
92156 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
92157 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
92158 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
92159 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
92160 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
92161 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
92162 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
92163 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
92164 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
92165 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
92166 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
92167 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
92168 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
92169 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
92170 PpxxVJkES/1Y+Zj0
92171 -----END CERTIFICATE-----
92172
92173 DigiCert Assured ID Root G2
92174 ===========================
92175 -----BEGIN CERTIFICATE-----
92176 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
92177 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
92178 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
92179 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
92180 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
92181 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
92182 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
92183 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
92184 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
92185 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
92186 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
92187 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
92188 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
92189 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
92190 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
92191 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
92192 IhNzbM8m9Yop5w==
92193 -----END CERTIFICATE-----
92194
92195 DigiCert Assured ID Root G3
92196 ===========================
92197 -----BEGIN CERTIFICATE-----
92198 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
92199 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
92200 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
92201 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
92202 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
92203 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
92204 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
92205 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
92206 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
92207 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
92208 1vUhZscv6pZjamVFkpUBtA==
92209 -----END CERTIFICATE-----
92210
92211 DigiCert Global Root G2
92212 =======================
92213 -----BEGIN CERTIFICATE-----
92214 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
92215 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
92216 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
92217 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
92218 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
92219 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
92220 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
92221 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
92222 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
92223 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
92224 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
92225 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
92226 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
92227 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
92228 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
92229 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
92230 MrY=
92231 -----END CERTIFICATE-----
92232
92233 DigiCert Global Root G3
92234 =======================
92235 -----BEGIN CERTIFICATE-----
92236 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
92237 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
92238 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
92239 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
92240 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
92241 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
92242 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
92243 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
92244 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
92245 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
92246 VOKa5Vt8sycX
92247 -----END CERTIFICATE-----
92248
92249 DigiCert Trusted Root G4
92250 ========================
92251 -----BEGIN CERTIFICATE-----
92252 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
92253 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
92254 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
92255 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
92256 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
92257 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
92258 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
92259 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
92260 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
92261 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
92262 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
92263 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
92264 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
92265 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
92266 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
92267 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
92268 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
92269 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
92270 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
92271 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
92272 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
92273 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
92274 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
92275 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
92276 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
92277 82Z+
92278 -----END CERTIFICATE-----
92279
92280 COMODO RSA Certification Authority
92281 ==================================
92282 -----BEGIN CERTIFICATE-----
92283 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
92284 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
92285 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
92286 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
92287 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
92288 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
92289 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
92290 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
92291 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
92292 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
92293 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
92294 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
92295 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
92296 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
92297 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
92298 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
92299 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
92300 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
92301 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
92302 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
92303 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
92304 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
92305 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
92306 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
92307 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
92308 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
92309 LaZRfyHBNVOFBkpdn627G190
92310 -----END CERTIFICATE-----
92311
92312 USERTrust RSA Certification Authority
92313 =====================================
92314 -----BEGIN CERTIFICATE-----
92315 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
92316 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
92317 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
92318 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
92319 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
92320 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
92321 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
92322 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
92323 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
92324 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
92325 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
92326 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
92327 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
92328 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
92329 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
92330 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
92331 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
92332 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
92333 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
92334 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
92335 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
92336 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
92337 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
92338 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
92339 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
92340 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
92341 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
92342 -----END CERTIFICATE-----
92343
92344 USERTrust ECC Certification Authority
92345 =====================================
92346 -----BEGIN CERTIFICATE-----
92347 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
92348 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
92349 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
92350 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
92351 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
92352 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
92353 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
92354 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
92355 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
92356 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
92357 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
92358 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
92359 -----END CERTIFICATE-----
92360
92361 GlobalSign ECC Root CA - R4
92362 ===========================
92363 -----BEGIN CERTIFICATE-----
92364 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
92365 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
92366 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
92367 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
92368 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
92369 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
92370 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
92371 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
92372 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
92373 -----END CERTIFICATE-----
92374
92375 GlobalSign ECC Root CA - R5
92376 ===========================
92377 -----BEGIN CERTIFICATE-----
92378 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
92379 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
92380 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
92381 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
92382 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
92383 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
92384 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
92385 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
92386 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
92387 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
92388 -----END CERTIFICATE-----
92389
92390 Staat der Nederlanden EV Root CA
92391 ================================
92392 -----BEGIN CERTIFICATE-----
92393 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
92394 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
92395 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
92396 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
92397 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
92398 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
92399 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
92400 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
92401 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
92402 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
92403 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
92404 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
92405 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
92406 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
92407 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
92408 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
92409 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
92410 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
92411 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
92412 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
92413 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
92414 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
92415 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
92416 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
92417 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
92418 -----END CERTIFICATE-----
92419
92420 IdenTrust Commercial Root CA 1
92421 ==============================
92422 -----BEGIN CERTIFICATE-----
92423 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
92424 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
92425 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
92426 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
92427 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
92428 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
92429 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
92430 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
92431 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
92432 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
92433 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
92434 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
92435 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
92436 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
92437 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
92438 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
92439 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
92440 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
92441 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
92442 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
92443 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
92444 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
92445 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
92446 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
92447 cGzM7vRX+Bi6hG6H
92448 -----END CERTIFICATE-----
92449
92450 IdenTrust Public Sector Root CA 1
92451 =================================
92452 -----BEGIN CERTIFICATE-----
92453 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
92454 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
92455 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
92456 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
92457 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
92458 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
92459 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
92460 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
92461 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
92462 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
92463 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
92464 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
92465 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
92466 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
92467 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
92468 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
92469 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
92470 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
92471 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
92472 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
92473 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
92474 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
92475 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
92476 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
92477 3Wl9af0AVqW3rLatt8o+Ae+c
92478 -----END CERTIFICATE-----
92479
92480 Entrust Root Certification Authority - G2
92481 =========================================
92482 -----BEGIN CERTIFICATE-----
92483 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
92484 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
92485 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
92486 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
92487 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
92488 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
92489 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
92490 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
92491 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
92492 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
92493 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
92494 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
92495 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
92496 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
92497 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
92498 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
92499 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
92500 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
92501 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
92502 e4pIb4tF9g==
92503 -----END CERTIFICATE-----
92504
92505 Entrust Root Certification Authority - EC1
92506 ==========================================
92507 -----BEGIN CERTIFICATE-----
92508 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
92509 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
92510 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
92511 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
92512 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
92513 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
92514 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
92515 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
92516 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
92517 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
92518 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
92519 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
92520 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
92521 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
92522 -----END CERTIFICATE-----
92523
92524 CFCA EV ROOT
92525 ============
92526 -----BEGIN CERTIFICATE-----
92527 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
92528 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
92529 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
92530 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
92531 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
92532 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
92533 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
92534 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
92535 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
92536 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
92537 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
92538 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
92539 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
92540 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
92541 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
92542 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
92543 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
92544 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
92545 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
92546 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
92547 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
92548 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
92549 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
92550 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
92551 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
92552 -----END CERTIFICATE-----
92553
92554 OISTE WISeKey Global Root GB CA
92555 ===============================
92556 -----BEGIN CERTIFICATE-----
92557 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
92558 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
92559 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
92560 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
92561 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
92562 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
92563 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
92564 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
92565 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
92566 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
92567 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
92568 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
92569 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
92570 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
92571 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
92572 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
92573 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
92574 -----END CERTIFICATE-----
92575
92576 SZAFIR ROOT CA2
92577 ===============
92578 -----BEGIN CERTIFICATE-----
92579 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
92580 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
92581 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
92582 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
92583 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
92584 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
92585 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
92586 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
92587 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
92588 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
92589 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
92590 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
92591 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
92592 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
92593 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
92594 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
92595 -----END CERTIFICATE-----
92596
92597 Certum Trusted Network CA 2
92598 ===========================
92599 -----BEGIN CERTIFICATE-----
92600 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
92601 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
92602 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
92603 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
92604 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
92605 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
92606 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
92607 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
92608 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
92609 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
92610 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
92611 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
92612 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
92613 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
92614 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
92615 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
92616 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
92617 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
92618 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
92619 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
92620 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
92621 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
92622 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
92623 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
92624 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
92625 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
92626 zAYspsbiDrW5viSP
92627 -----END CERTIFICATE-----
92628
92629 Hellenic Academic and Research Institutions RootCA 2015
92630 =======================================================
92631 -----BEGIN CERTIFICATE-----
92632 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
92633 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
92634 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
92635 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
92636 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
92637 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
92638 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
92639 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
92640 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
92641 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
92642 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
92643 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
92644 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
92645 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
92646 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
92647 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
92648 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
92649 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
92650 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
92651 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
92652 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
92653 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
92654 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
92655 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
92656 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
92657 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
92658 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
92659 p/UsQu0yrbYhnr68
92660 -----END CERTIFICATE-----
92661
92662 Hellenic Academic and Research Institutions ECC RootCA 2015
92663 ===========================================================
92664 -----BEGIN CERTIFICATE-----
92665 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
92666 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
92667 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
92668 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
92669 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
92670 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
92671 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
92672 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
92673 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
92674 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
92675 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
92676 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
92677 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
92678 -----END CERTIFICATE-----
92679
92680 ISRG Root X1
92681 ============
92682 -----BEGIN CERTIFICATE-----
92683 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
92684 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
92685 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
92686 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
92687 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
92688 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
92689 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
92690 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
92691 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
92692 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
92693 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
92694 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
92695 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
92696 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
92697 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
92698 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
92699 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
92700 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
92701 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
92702 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
92703 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
92704 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
92705 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
92706 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
92707 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
92708 -----END CERTIFICATE-----
92709
92710 AC RAIZ FNMT-RCM
92711 ================
92712 -----BEGIN CERTIFICATE-----
92713 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
92714 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
92715 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
92716 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
92717 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
92718 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
92719 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
92720 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
92721 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
92722 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
92723 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
92724 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
92725 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
92726 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
92727 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
92728 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
92729 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
92730 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
92731 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
92732 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
92733 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
92734 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
92735 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
92736 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
92737 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
92738 -----END CERTIFICATE-----
92739
92740 Amazon Root CA 1
92741 ================
92742 -----BEGIN CERTIFICATE-----
92743 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
92744 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
92745 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
92746 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
92747 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
92748 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
92749 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
92750 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
92751 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
92752 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
92753 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
92754 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
92755 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
92756 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
92757 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
92758 -----END CERTIFICATE-----
92759
92760 Amazon Root CA 2
92761 ================
92762 -----BEGIN CERTIFICATE-----
92763 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
92764 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
92765 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
92766 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
92767 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
92768 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
92769 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
92770 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
92771 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
92772 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
92773 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
92774 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
92775 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
92776 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
92777 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
92778 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
92779 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
92780 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
92781 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
92782 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
92783 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
92784 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
92785 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
92786 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
92787 -----END CERTIFICATE-----
92788
92789 Amazon Root CA 3
92790 ================
92791 -----BEGIN CERTIFICATE-----
92792 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
92793 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
92794 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
92795 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
92796 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
92797 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
92798 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
92799 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
92800 -----END CERTIFICATE-----
92801
92802 Amazon Root CA 4
92803 ================
92804 -----BEGIN CERTIFICATE-----
92805 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
92806 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
92807 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
92808 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
92809 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
92810 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
92811 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
92812 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
92813 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
92814 -----END CERTIFICATE-----
92815
92816 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
92817 =============================================
92818 -----BEGIN CERTIFICATE-----
92819 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
92820 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
92821 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
92822 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
92823 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
92824 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
92825 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
92826 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
92827 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
92828 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
92829 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
92830 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
92831 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
92832 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
92833 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
92834 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
92835 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
92836 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
92837 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
92838 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
92839 -----END CERTIFICATE-----
92840
92841 GDCA TrustAUTH R5 ROOT
92842 ======================
92843 -----BEGIN CERTIFICATE-----
92844 MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
92845 BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
92846 DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
92847 YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
92848 IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
92849 AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
92850 AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
92851 OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
92852 pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
92853 9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
92854 xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
92855 R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
92856 D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
92857 oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
92858 9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
92859 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
92860 p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
92861 H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
92862 6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
92863 +PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
92864 HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
92865 F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
92866 8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
92867 /EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
92868 aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
92869 -----END CERTIFICATE-----
92870
92871 TrustCor RootCert CA-1
92872 ======================
92873 -----BEGIN CERTIFICATE-----
92874 MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP
92875 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
92876 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
92877 dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx
92878 MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu
92879 YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe
92880 VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy
92881 dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq
92882 jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4
92883 pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0
92884 JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h
92885 gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw
92886 /Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j
92887 BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
92888 AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5
92889 mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
92890 ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C
92891 qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P
92892 3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk=
92893 -----END CERTIFICATE-----
92894
92895 TrustCor RootCert CA-2
92896 ======================
92897 -----BEGIN CERTIFICATE-----
92898 MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w
92899 DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT
92900 eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0
92901 eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy
92902 MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h
92903 bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
92904 cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0
92905 IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb
92906 ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk
92907 RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1
92908 oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb
92909 XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1
92910 /p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q
92911 jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP
92912 eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg
92913 rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
92914 8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU
92915 2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD
92916 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h
92917 Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp
92918 kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv
92919 2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3
92920 S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw
92921 PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv
92922 DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU
92923 RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE
92924 xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX
92925 RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ
92926 -----END CERTIFICATE-----
92927
92928 TrustCor ECA-1
92929 ==============
92930 -----BEGIN CERTIFICATE-----
92931 MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP
92932 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
92933 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
92934 dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw
92935 N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5
92936 MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y
92937 IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG
92938 SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR
92939 MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23
92940 xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc
92941 p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+
92942 fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj
92943 YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL
92944 f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
92945 AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u
92946 /ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
92947 hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs
92948 J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC
92949 jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g==
92950 -----END CERTIFICATE-----
92951
92952 SSL.com Root Certification Authority RSA
92953 ========================================
92954 -----BEGIN CERTIFICATE-----
92955 MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
92956 BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
92957 MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
92958 MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
92959 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
92960 LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
92961 ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
92962 Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
92963 P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
92964 oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
92965 k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
92966 fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
92967 gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
92968 UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
92969 1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
92970 bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
92971 HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
92972 AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
92973 dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
92974 ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
92975 u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
92976 erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
92977 MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
92978 vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
92979 Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
92980 wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
92981 WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
92982 -----END CERTIFICATE-----
92983
92984 SSL.com Root Certification Authority ECC
92985 ========================================
92986 -----BEGIN CERTIFICATE-----
92987 MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
92988 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
92989 BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
92990 MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
92991 BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
92992 bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
92993 BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
92994 8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
92995 hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
92996 jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
92997 e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
92998 5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
92999 -----END CERTIFICATE-----
93000
93001 SSL.com EV Root Certification Authority RSA R2
93002 ==============================================
93003 -----BEGIN CERTIFICATE-----
93004 MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
93005 DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
93006 MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
93007 MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
93008 DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
93009 VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
93010 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
93011 hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
93012 cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
93013 Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
93014 B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
93015 CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
93016 9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
93017 RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
93018 JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
93019 +qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
93020 HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
93021 qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
93022 ++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
93023 Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
93024 guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
93025 OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
93026 CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
93027 lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
93028 rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
93029 hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
93030 9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
93031 -----END CERTIFICATE-----
93032
93033 SSL.com EV Root Certification Authority ECC
93034 ===========================================
93035 -----BEGIN CERTIFICATE-----
93036 MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
93037 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
93038 BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
93039 MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
93040 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
93041 LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
93042 BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
93043 3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
93044 BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
93045 5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
93046 N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
93047 m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
93048 -----END CERTIFICATE-----
93049
93050 GlobalSign Root CA - R6
93051 =======================
93052 -----BEGIN CERTIFICATE-----
93053 MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
93054 R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
93055 b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
93056 YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
93057 U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
93058 grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
93059 3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
93060 vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
93061 PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
93062 azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
93063 WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
93064 CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
93065 0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
93066 b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
93067 AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
93068 HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
93069 nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
93070 lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
93071 BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
93072 Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
93073 3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
93074 0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
93075 uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
93076 oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
93077 JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
93078 -----END CERTIFICATE-----
93079
93080 OISTE WISeKey Global Root GC CA
93081 ===============================
93082 -----BEGIN CERTIFICATE-----
93083 MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
93084 SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
93085 MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
93086 Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
93087 ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
93088 bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
93089 VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
93090 NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
93091 BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
93092 AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
93093 AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
93094 -----END CERTIFICATE-----
93095
93096 GTS Root R1
93097 ===========
93098 -----BEGIN CERTIFICATE-----
93099 MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
93100 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
93101 b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
93102 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi
93103 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx
93104 9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r
93105 aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW
93106 r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM
93107 LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly
93108 4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr
93109 06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
93110 wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om
93111 3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu
93112 JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
93113 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM
93114 BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
93115 d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv
93116 fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm
93117 ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b
93118 gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq
93119 4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr
93120 tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo
93121 pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0
93122 sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql
93123 CFF1pkgl
93124 -----END CERTIFICATE-----
93125
93126 GTS Root R2
93127 ===========
93128 -----BEGIN CERTIFICATE-----
93129 MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
93130 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
93131 b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
93132 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi
93133 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk
93134 k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo
93135 7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI
93136 m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm
93137 dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu
93138 ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz
93139 cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
93140 Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl
93141 aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy
93142 5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
93143 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM
93144 BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
93145 vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ
93146 +YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw
93147 c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da
93148 WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r
93149 n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu
93150 Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ
93151 7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs
93152 gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld
93153 o/DUhgkC
93154 -----END CERTIFICATE-----
93155
93156 GTS Root R3
93157 ===========
93158 -----BEGIN CERTIFICATE-----
93159 MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
93160 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
93161 UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
93162 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq
93163 hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU
93164 Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej
93165 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP
93166 0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0
93167 glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa
93168 KaqW04MjyaR7YbPMAuhd
93169 -----END CERTIFICATE-----
93170
93171 GTS Root R4
93172 ===========
93173 -----BEGIN CERTIFICATE-----
93174 MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
93175 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
93176 UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
93177 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq
93178 hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa
93179 6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj
93180 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV
93181 2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI
93182 N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x
93183 zPKwTdb+mciUqXWi4w==
93184 -----END CERTIFICATE-----
93185
93186 UCA Global G2 Root
93187 ==================
93188 -----BEGIN CERTIFICATE-----
93189 MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG
93190 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x
93191 NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU
93192 cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
93193 MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT
93194 oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV
93195 8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS
93196 h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o
93197 LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/
93198 R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe
93199 KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa
93200 4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc
93201 OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97
93202 8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
93203 BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo
93204 5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
93205 1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A
93206 Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9
93207 yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX
93208 c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo
93209 jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk
93210 bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x
93211 ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn
93212 RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A==
93213 -----END CERTIFICATE-----
93214
93215 UCA Extended Validation Root
93216 ============================
93217 -----BEGIN CERTIFICATE-----
93218 MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
93219 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u
93220 IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G
93221 A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi
93222 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs
93223 iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF
93224 Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu
93225 eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR
93226 59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH
93227 0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR
93228 el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv
93229 B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth
93230 WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS
93231 NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS
93232 3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL
93233 BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
93234 ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM
93235 aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4
93236 dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb
93237 +7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW
93238 F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi
93239 GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc
93240 GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi
93241 djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr
93242 dhh2n1ax
93243 -----END CERTIFICATE-----
93244
93245 Certigna Root CA
93246 ================
93247 -----BEGIN CERTIFICATE-----
93248 MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE
93249 BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ
93250 MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda
93251 MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz
93252 MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
93253 DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX
93254 stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz
93255 KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8
93256 JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16
93257 XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq
93258 4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej
93259 wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ
93260 lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI
93261 jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/
93262 /TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
93263 HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
93264 1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy
93265 dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h
93266 LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl
93267 cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt
93268 OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP
93269 TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq
93270 7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3
93271 4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd
93272 8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS
93273 6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY
93274 tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
93275 aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
93276 E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
93277 -----END CERTIFICATE-----
93278
93279 emSign Root CA - G1
93280 ===================
93281 -----BEGIN CERTIFICATE-----
93282 MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
93283 MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
93284 ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
93285 ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
93286 aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
93287 IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
93288 LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
93289 cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
93290 DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
93291 6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
93292 hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
93293 MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
93294 vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
93295 NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
93296 +Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
93297 U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
93298 iN66zB+Afko=
93299 -----END CERTIFICATE-----
93300
93301 emSign ECC Root CA - G3
93302 =======================
93303 -----BEGIN CERTIFICATE-----
93304 MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
93305 A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
93306 MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
93307 MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
93308 ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
93309 RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
93310 58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
93311 MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
93312 AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
93313 CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
93314 jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
93315 -----END CERTIFICATE-----
93316
93317 emSign Root CA - C1
93318 ===================
93319 -----BEGIN CERTIFICATE-----
93320 MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
93321 EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
93322 Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
93323 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
93324 ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
93325 ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
93326 Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
93327 OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
93328 I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
93329 lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
93330 XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
93331 ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
93332 /6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
93333 NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
93334 wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
93335 BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
93336 -----END CERTIFICATE-----
93337
93338 emSign ECC Root CA - C3
93339 =======================
93340 -----BEGIN CERTIFICATE-----
93341 MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
93342 A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
93343 Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
93344 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
93345 ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
93346 6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
93347 SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
93348 B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
93349 MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
93350 ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
93351 -----END CERTIFICATE-----
93352
93353 Hongkong Post Root CA 3
93354 =======================
93355 -----BEGIN CERTIFICATE-----
93356 MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
93357 A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
93358 Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
93359 MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
93360 bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
93361 SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
93362 iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
93363 jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
93364 5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
93365 sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
93366 0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
93367 JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
93368 y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
93369 +bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
93370 xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
93371 AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
93372 i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
93373 AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
93374 W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
93375 y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
93376 +BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
93377 eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
93378 9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
93379 nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
93380 hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
93381 60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
93382 dBb9HxEGmpv0
93383 -----END CERTIFICATE-----
93384
93385 Entrust Root Certification Authority - G4
93386 =========================================
93387 -----BEGIN CERTIFICATE-----
93388 MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV
93389 BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu
93390 bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1
93391 dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
93392 dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT
93393 AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
93394 L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv
93395 cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv
93396 cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D
93397 umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV
93398 3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds
93399 8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ
93400 e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7
93401 ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X
93402 xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV
93403 7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
93404 dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW
93405 Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T
93406 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n
93407 MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q
93408 jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht
93409 7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK
93410 YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt
93411 jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+
93412 m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW
93413 RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA
93414 JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G
93415 +TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT
93416 kcpG2om3PVODLAgfi49T3f+sHw==
93417 -----END CERTIFICATE-----
93418
93419 Microsoft ECC Root Certificate Authority 2017
93420 =============================================
93421 -----BEGIN CERTIFICATE-----
93422 MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
93423 UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND
93424 IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4
93425 MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
93426 NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ
93427 BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6
93428 thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB
93429 eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM
93430 +Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf
93431 Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR
93432 eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
93433 -----END CERTIFICATE-----
93434
93435 Microsoft RSA Root Certificate Authority 2017
93436 =============================================
93437 -----BEGIN CERTIFICATE-----
93438 MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG
93439 EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg
93440 UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw
93441 NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
93442 MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw
93443 ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml
93444 7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e
93445 S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7
93446 1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+
93447 dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F
93448 yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS
93449 MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr
93450 lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ
93451 0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ
93452 ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw
93453 DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
93454 NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og
93455 6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80
93456 dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk
93457 +ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex
93458 /2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy
93459 AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW
93460 ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE
93461 7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT
93462 c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D
93463 5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E
93464 -----END CERTIFICATE-----
93465
93466 e-Szigno Root CA 2017
93467 =====================
93468 -----BEGIN CERTIFICATE-----
93469 MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw
93470 DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt
93471 MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa
93472 Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE
93473 CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp
93474 Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx
93475 s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G
93476 A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv
93477 vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA
93478 tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO
93479 svxyqltZ+efcMQ==
93480 -----END CERTIFICATE-----
93481
93482 certSIGN Root CA G2
93483 ===================
93484 -----BEGIN CERTIFICATE-----
93485 MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw
93486 EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy
93487 MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH
93488 TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
93489 ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05
93490 N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk
93491 abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg
93492 wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp
93493 dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh
93494 ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732
93495 jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf
93496 95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc
93497 z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL
93498 iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud
93499 DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB
93500 ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
93501 b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB
93502 /AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5
93503 8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5
93504 BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW
93505 atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU
93506 Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M
93507 NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N
93508 0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc=
93509 -----END CERTIFICATE-----
93510
93511 Trustwave Global Certification Authority
93512 ========================================
93513 -----BEGIN CERTIFICATE-----
93514 MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV
93515 UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
93516 ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
93517 IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV
93518 UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
93519 ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
93520 IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29
93521 zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf
93522 LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq
93523 stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o
93524 WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+
93525 OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40
93526 Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE
93527 uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm
93528 +9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj
93529 ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
93530 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB
93531 BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H
93532 PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H
93533 ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla
93534 4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R
93535 vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd
93536 zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O
93537 856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH
93538 Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu
93539 3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP
93540 29FpHOTKyeC2nOnOcXHebD8WpHk=
93541 -----END CERTIFICATE-----
93542
93543 Trustwave Global ECC P256 Certification Authority
93544 =================================================
93545 -----BEGIN CERTIFICATE-----
93546 MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER
93547 MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
93548 b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp
93549 Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD
93550 VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
93551 dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1
93552 NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj
93553 43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm
93554 P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt
93555 0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz
93556 RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
93557 -----END CERTIFICATE-----
93558
93559 Trustwave Global ECC P384 Certification Authority
93560 =================================================
93561 -----BEGIN CERTIFICATE-----
93562 MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER
93563 MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
93564 b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp
93565 Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD
93566 VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
93567 dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4
93568 NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH
93569 Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr
93570 /TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV
93571 HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn
93572 ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl
93573 CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw==
93574 -----END CERTIFICATE-----
93575
93576 NAVER Global Root Certification Authority
93577 =========================================
93578 -----BEGIN CERTIFICATE-----
93579 MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG
93580 A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD
93581 DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4
93582 NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT
93583 UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv
93584 biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb
93585 UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW
93586 +j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7
93587 XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2
93588 aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4
93589 Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z
93590 VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B
93591 A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai
93592 cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy
93593 YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV
93594 HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
93595 Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK
93596 21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB
93597 jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx
93598 hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg
93599 E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH
93600 D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ
93601 A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY
93602 qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG
93603 I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg
93604 kpzNNIaRkPpkUZ3+/uul9XXeifdy
93605 -----END CERTIFICATE-----
93606
93607 AC RAIZ FNMT-RCM SERVIDORES SEGUROS
93608 ===================================
93609 -----BEGIN CERTIFICATE-----
93610 MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF
93611 UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy
93612 NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4
93613 MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt
93614 UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB
93615 QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
93616 BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2
93617 LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw
93618 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG
93619 SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD
93620 zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c=
93621 -----END CERTIFICATE-----
93622
93623 GlobalSign Root R46
93624 ===================
93625 -----BEGIN CERTIFICATE-----
93626 MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV
93627 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv
93628 b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX
93629 BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi
93630 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es
93631 CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/
93632 r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje
93633 2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt
93634 bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj
93635 K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4
93636 12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on
93637 ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls
93638 eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9
93639 vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD
93640 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM
93641 BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
93642 JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy
93643 gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92
93644 CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm
93645 OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq
93646 JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye
93647 qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz
93648 nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7
93649 DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3
93650 QEUxeCp6
93651 -----END CERTIFICATE-----
93652
93653 GlobalSign Root E46
93654 ===================
93655 -----BEGIN CERTIFICATE-----
93656 MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT
93657 AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg
93658 RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV
93659 BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq
93660 hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB
93661 jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj
93662 QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL
93663 gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk
93664 vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+
93665 CAezNIm8BZ/3Hobui3A=
93666 -----END CERTIFICATE-----
93667
93668 GLOBALTRUST 2020
93669 ================
93670 -----BEGIN CERTIFICATE-----
93671 MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx
93672 IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT
93673 VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh
93674 BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy
93675 MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi
93676 D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO
93677 VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM
93678 CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm
93679 fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA
93680 A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR
93681 JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG
93682 DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU
93683 clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ
93684 mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
93685 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud
93686 IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
93687 VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw
93688 4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9
93689 iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS
93690 8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2
93691 HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS
93692 vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918
93693 oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF
93694 YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl
93695 gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
93696 -----END CERTIFICATE-----
93697
93698 ANF Secure Server Root CA
93699 =========================
93700 -----BEGIN CERTIFICATE-----
93701 MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4
93702 NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv
93703 bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg
93704 Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw
93705 MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw
93706 EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC
93707 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz
93708 BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv
93709 T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv
93710 B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse
93711 zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM
93712 VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j
93713 7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z
93714 JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe
93715 8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO
93716 Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
93717 o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E
93718 BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ
93719 UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx
93720 j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt
93721 dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM
93722 5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb
93723 5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54
93724 EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H
93725 hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy
93726 g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3
93727 r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
93728 -----END CERTIFICATE-----
93729
93730 Certum EC-384 CA
93731 ================
93732 -----BEGIN CERTIFICATE-----
93733 MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ
93734 TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
93735 dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2
93736 MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh
93737 dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx
93738 GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq
93739 vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn
93740 iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
93741 VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo
93742 ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0
93743 QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
93744 -----END CERTIFICATE-----
93745
93746 Certum Trusted Root CA
93747 ======================
93748 -----BEGIN CERTIFICATE-----
93749 MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG
93750 EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g
93751 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew
93752 HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY
93753 QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB
93754 dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB
93755 AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p
93756 fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52
93757 HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2
93758 fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt
93759 g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4
93760 NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk
93761 fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ
93762 P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY
93763 njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK
93764 HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
93765 vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL
93766 LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s
93767 ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K
93768 h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8
93769 CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA
93770 4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo
93771 WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj
93772 6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT
93773 OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck
93774 bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
93775 -----END CERTIFICATE-----
93776
93777 TunTrust Root CA
93778 ================
93779 -----BEGIN CERTIFICATE-----
93780 MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG
93781 A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj
93782 dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw
93783 NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD
93784 ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw
93785 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz
93786 2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b
93787 bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7
93788 NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd
93789 gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW
93790 VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f
93791 Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ
93792 juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas
93793 DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS
93794 VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI
93795 04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
93796 90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl
93797 0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd
93798 Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY
93799 YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp
93800 adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x
93801 xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP
93802 jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM
93803 MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z
93804 ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r
93805 AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
93806 -----END CERTIFICATE-----
93807
93808 HARICA TLS RSA Root CA 2021
93809 ===========================
93810 -----BEGIN CERTIFICATE-----
93811 MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG
93812 EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
93813 cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz
93814 OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl
93815 bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB
93816 IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN
93817 JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu
93818 a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y
93819 Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K
93820 5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv
93821 dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR
93822 0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH
93823 GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm
93824 haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ
93825 CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G
93826 A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
93827 AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU
93828 EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq
93829 QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD
93830 QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR
93831 j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5
93832 vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0
93833 qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6
93834 Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/
93835 PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn
93836 kf3/W9b3raYvAwtt41dU63ZTGI0RmLo=
93837 -----END CERTIFICATE-----
93838
93839 HARICA TLS ECC Root CA 2021
93840 ===========================
93841 -----BEGIN CERTIFICATE-----
93842 MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH
93843 UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD
93844 QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX
93845 DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj
93846 IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv
93847 b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l
93848 AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b
93849 ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW
93850 0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi
93851 rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw
93852 CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
93853 -----END CERTIFICATE-----
93854 <?php
93855
93856 if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
93857     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
93858 }
93859
93860 setlocale(LC_ALL, 'C');
93861 require __DIR__.'/../src/bootstrap.php';
93862
93863 use Composer\Console\Application;
93864 use Composer\XdebugHandler\XdebugHandler;
93865 use Composer\Util\ErrorHandler;
93866
93867 error_reporting(-1);
93868
93869 // Restart without Xdebug
93870 $xdebug = new XdebugHandler('Composer', '--ansi');
93871 $xdebug->check();
93872 unset($xdebug);
93873
93874 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '4.0', '>=')) {
93875     echo 'HHVM 4.0 has dropped support for Composer, please use PHP instead. Aborting.'.PHP_EOL;
93876     exit(1);
93877 }
93878
93879 if (function_exists('ini_set')) {
93880     @ini_set('display_errors', 1);
93881
93882     $memoryInBytes = function ($value) {
93883         $unit = strtolower(substr($value, -1, 1));
93884         $value = (int) $value;
93885         switch($unit) {
93886             case 'g':
93887                 $value *= 1024;
93888                 // no break (cumulative multiplier)
93889             case 'm':
93890                 $value *= 1024;
93891                 // no break (cumulative multiplier)
93892             case 'k':
93893                 $value *= 1024;
93894         }
93895
93896         return $value;
93897     };
93898
93899     $memoryLimit = trim(ini_get('memory_limit'));
93900     // Increase memory_limit if it is lower than 1.5GB
93901     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
93902         @ini_set('memory_limit', '1536M');
93903     }
93904     // Set user defined memory limit
93905     if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
93906         @ini_set('memory_limit', $memoryLimit);
93907     }
93908     unset($memoryInBytes, $memoryLimit);
93909 }
93910
93911 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
93912
93913 ErrorHandler::register();
93914
93915 // run the command application
93916 $application = new Application();
93917 $application->run();
93918
93919 Copyright (c) Nils Adermann, Jordi Boggiano
93920
93921 Permission is hereby granted, free of charge, to any person obtaining a copy
93922 of this software and associated documentation files (the "Software"), to deal
93923 in the Software without restriction, including without limitation the rights
93924 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
93925 copies of the Software, and to permit persons to whom the Software is furnished
93926 to do so, subject to the following conditions:
93927
93928 The above copyright notice and this permission notice shall be included in all
93929 copies or substantial portions of the Software.
93930
93931 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
93932 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
93933 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
93934 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
93935 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
93936 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
93937 THE SOFTWARE.
93938
93939 ;y9B\9dT}û?z¦qrü\82{V q
93940 \ 2\0\0\0GBMB