VcsDriver.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Repository\Vcs;
  12. use Composer\IO\IOInterface;
  13. /**
  14. * A driver implementation for driver with authentification interaction.
  15. *
  16. * @author François Pluchino <francois.pluchino@opendisplay.com>
  17. */
  18. abstract class VcsDriver
  19. {
  20. protected $url;
  21. protected $io;
  22. private $firstCall;
  23. /**
  24. * Constructor.
  25. *
  26. * @param string $url The URL
  27. * @param IOInterface $io The IO instance
  28. */
  29. public function __construct($url, IOInterface $io)
  30. {
  31. $this->url = $url;
  32. $this->io = $io;
  33. $this->firstCall = true;
  34. }
  35. /**
  36. * Get the https or http protocol.
  37. *
  38. * @return string The correct type of protocol
  39. */
  40. protected function getScheme()
  41. {
  42. if (extension_loaded('openssl')) {
  43. return 'https';
  44. }
  45. return 'http';
  46. }
  47. /**
  48. * Get the remote content.
  49. *
  50. * @param string $url The URL of content
  51. *
  52. * @return mixed The result
  53. */
  54. protected function getContents($url)
  55. {
  56. $auth = $this->io->getAuthentification($this->url);
  57. // curl options
  58. $defaults = array(
  59. CURLOPT_RETURNTRANSFER => true,
  60. CURLOPT_BINARYTRANSFER => true,
  61. CURLOPT_BUFFERSIZE => 64000,
  62. CURLOPT_FOLLOWLOCATION => true,
  63. CURLOPT_NOPROGRESS => true,
  64. CURLOPT_URL => $url,
  65. CURLOPT_HTTPGET => true,
  66. CURLOPT_SSL_VERIFYPEER => false
  67. );
  68. // add authorization to curl options
  69. if ($this->io->hasAuthentification($this->url)) {
  70. $defaults[CURLOPT_USERPWD] = $auth['username'] . ':' . $auth['password'];
  71. } else if (null !== $this->io->getLastUsername()) {
  72. $defaults[CURLOPT_USERPWD] = $this->io->getLastUsername() . ':' . $this->io->getLastPassword();
  73. }
  74. // init curl
  75. $ch = curl_init();
  76. curl_setopt_array($ch, $defaults);
  77. // run curl
  78. $curl_result = curl_exec($ch);
  79. $curl_info = curl_getinfo($ch);
  80. $curl_errorCode = curl_errno($ch);
  81. $curl_error = curl_error($ch);
  82. $code = $curl_info['http_code'];
  83. $code = null ? 0 : $code;
  84. //close streams
  85. curl_close($ch);
  86. // for private repository returning 404 error when the authentification is incorrect
  87. $ps = $this->firstCall && 404 === $code && null === $this->io->getLastUsername() && null === $auth['username'];
  88. if ($this->firstCall) {
  89. $this->firstCall = false;
  90. }
  91. // auth required
  92. if (401 === $code || $ps) {
  93. if (!$this->io->isInteractive()) {
  94. $mess = "The '$url' URL not found";
  95. if (401 === $code || $ps) {
  96. $mess = "The '$url' URL required the authentification.\nYou must be used the interactive console";
  97. }
  98. throw new \LogicException($mess);
  99. }
  100. $this->io->writeln("Authorization required for <info>" . $this->owner.'/' . $this->repository . "</info>:");
  101. $username = $this->io->ask(' Username: ');
  102. $password = $this->io->askAndHideAnswer(' Password: ');
  103. $this->io->setAuthentification($this->url, $username, $password);
  104. return $this->getContents($url);
  105. } else if (404 === $code) {
  106. throw new \LogicException("The '$url' URL not found");
  107. }
  108. return $curl_result;
  109. }
  110. }