[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/joomla/http/src/Transport/ -> Stream.php (source)

   1  <?php
   2  /**
   3   * Part of the Joomla Framework Http Package
   4   *
   5   * @copyright  Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
   6   * @license    GNU General Public License version 2 or later; see LICENSE
   7   */
   8  
   9  namespace Joomla\Http\Transport;
  10  
  11  use Composer\CaBundle\CaBundle;
  12  use Joomla\Http\AbstractTransport;
  13  use Joomla\Http\Exception\InvalidResponseCodeException;
  14  use Joomla\Http\Response;
  15  use Joomla\Uri\Uri;
  16  use Joomla\Uri\UriInterface;
  17  use Laminas\Diactoros\Stream as StreamResponse;
  18  
  19  /**
  20   * HTTP transport class for using PHP streams.
  21   *
  22   * @since  1.0
  23   */
  24  class Stream extends AbstractTransport
  25  {
  26      /**
  27       * Send a request to the server and return a Response object with the response.
  28       *
  29       * @param   string        $method     The HTTP method for sending the request.
  30       * @param   UriInterface  $uri        The URI to the resource to request.
  31       * @param   mixed         $data       Either an associative array or a string to be sent with the request.
  32       * @param   array         $headers    An array of request headers to send with the request.
  33       * @param   integer       $timeout    Read timeout in seconds.
  34       * @param   string        $userAgent  The optional user agent string to send with the request.
  35       *
  36       * @return  Response
  37       *
  38       * @since   1.0
  39       * @throws  \RuntimeException
  40       */
  41  	public function request($method, UriInterface $uri, $data = null, array $headers = [], $timeout = null, $userAgent = null)
  42      {
  43          // Create the stream context options array with the required method offset.
  44          $options = ['method' => strtoupper($method)];
  45  
  46          // If data exists let's encode it and make sure our Content-Type header is set.
  47          if (isset($data))
  48          {
  49              // If the data is a scalar value simply add it to the stream context options.
  50              if (is_scalar($data))
  51              {
  52                  $options['content'] = $data;
  53              }
  54              else
  55              {
  56                  // Otherwise we need to encode the value first.
  57                  $options['content'] = http_build_query($data);
  58              }
  59  
  60              if (!isset($headers['Content-Type']))
  61              {
  62                  $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
  63              }
  64  
  65              // Add the relevant headers.
  66              $headers['Content-Length'] = \strlen($options['content']);
  67          }
  68  
  69          // If an explicit timeout is given user it.
  70          if (isset($timeout))
  71          {
  72              $options['timeout'] = (int) $timeout;
  73          }
  74  
  75          // If an explicit user agent is given use it.
  76          if (isset($userAgent))
  77          {
  78              $options['user_agent'] = $userAgent;
  79          }
  80  
  81          // Ignore HTTP errors so that we can capture them.
  82          $options['ignore_errors'] = 1;
  83  
  84          // Follow redirects.
  85          $options['follow_location'] = (int) $this->getOption('follow_location', 1);
  86  
  87          // Configure protocol version, use transport's default if not set otherwise.
  88          $options['follow_location'] = $this->getOption('protocolVersion', '1.0');
  89  
  90          // Add the proxy configuration if enabled
  91          if ($this->getOption('proxy.enabled', false))
  92          {
  93              $options['request_fulluri'] = true;
  94  
  95              if ($this->getOption('proxy.host') && $this->getOption('proxy.port'))
  96              {
  97                  $options['proxy'] = $this->getOption('proxy.host') . ':' . (int) $this->getOption('proxy.port');
  98              }
  99  
 100              // If authentication details are provided, add those as well
 101              if ($this->getOption('proxy.user') && $this->getOption('proxy.password'))
 102              {
 103                  $headers['Proxy-Authorization'] = 'Basic ' . base64_encode($this->getOption('proxy.user') . ':' . $this->getOption('proxy.password'));
 104              }
 105          }
 106  
 107          // Build the headers string for the request.
 108          if (!empty($headers))
 109          {
 110              $headerString = '';
 111  
 112              foreach ($headers as $key => $value)
 113              {
 114                  if (\is_array($value))
 115                  {
 116                      foreach ($value as $header)
 117                      {
 118                          $headerString .= "$key: $header\r\n";
 119                      }
 120                  }
 121                  else
 122                  {
 123                      $headerString .= "$key: $value\r\n";
 124                  }
 125              }
 126  
 127              // Add the headers string into the stream context options array.
 128              $options['header'] = trim($headerString, "\r\n");
 129          }
 130  
 131          // Authentication, if needed
 132          if ($uri instanceof Uri && $this->getOption('userauth') && $this->getOption('passwordauth'))
 133          {
 134              $uri->setUser($this->getOption('userauth'));
 135              $uri->setPass($this->getOption('passwordauth'));
 136          }
 137  
 138          // Set any custom transport options
 139          foreach ($this->getOption('transport.stream', []) as $key => $value)
 140          {
 141              $options[$key] = $value;
 142          }
 143  
 144          // Get the current context options.
 145          $contextOptions = stream_context_get_options(stream_context_get_default());
 146  
 147          // Add our options to the currently defined options, if any.
 148          $contextOptions['http'] = isset($contextOptions['http']) ? array_merge($contextOptions['http'], $options) : $options;
 149  
 150          // Create the stream context for the request.
 151          $streamOptions = [
 152              'http' => $options,
 153              'ssl'  => [
 154                  'verify_peer'      => true,
 155                  'verify_depth'     => 5,
 156                  'verify_peer_name' => true,
 157              ],
 158          ];
 159  
 160          // The cacert may be a file or path
 161          $certpath = $this->getOption('stream.certpath', CaBundle::getSystemCaRootBundlePath());
 162  
 163          if (is_dir($certpath))
 164          {
 165              $streamOptions['ssl']['capath'] = $certpath;
 166          }
 167          else
 168          {
 169              $streamOptions['ssl']['cafile'] = $certpath;
 170          }
 171  
 172          $context = stream_context_create($streamOptions);
 173  
 174          // Capture PHP errors
 175          $php_errormsg = '';
 176          $trackErrors  = ini_get('track_errors');
 177          ini_set('track_errors', true);
 178  
 179          // Open the stream for reading.
 180          $stream = @fopen((string) $uri, 'r', false, $context);
 181  
 182          if (!$stream)
 183          {
 184              if (!$php_errormsg)
 185              {
 186                  // Error but nothing from php? Create our own
 187                  $php_errormsg = sprintf('Could not connect to resource: %s', $uri);
 188              }
 189  
 190              // Restore error tracking to give control to the exception handler
 191              ini_set('track_errors', $trackErrors);
 192  
 193              throw new \RuntimeException($php_errormsg);
 194          }
 195  
 196          // Restore error tracking to what it was before.
 197          ini_set('track_errors', $trackErrors);
 198  
 199          // Get the metadata for the stream, including response headers.
 200          $metadata = stream_get_meta_data($stream);
 201  
 202          // Get the contents from the stream.
 203          $content = stream_get_contents($stream);
 204  
 205          // Close the stream.
 206          fclose($stream);
 207  
 208          $headers = [];
 209  
 210          if (isset($metadata['wrapper_data']['headers']))
 211          {
 212              $headers = $metadata['wrapper_data']['headers'];
 213          }
 214          elseif (isset($metadata['wrapper_data']))
 215          {
 216              $headers = $metadata['wrapper_data'];
 217          }
 218  
 219          return $this->getResponse($headers, $content);
 220      }
 221  
 222      /**
 223       * Method to get a response object from a server response.
 224       *
 225       * @param   array   $headers  The response headers as an array.
 226       * @param   string  $body     The response body as a string.
 227       *
 228       * @return  Response
 229       *
 230       * @since   1.0
 231       * @throws  InvalidResponseCodeException
 232       */
 233  	protected function getResponse(array $headers, $body)
 234      {
 235          // Get the response code from the first offset of the response headers.
 236          preg_match('/[0-9]{3}/', array_shift($headers), $matches);
 237          $code = $matches[0];
 238  
 239          if (!is_numeric($code))
 240          {
 241              // No valid response code was detected.
 242              throw new InvalidResponseCodeException('No HTTP response code found.');
 243          }
 244  
 245          $statusCode      = (int) $code;
 246          $verifiedHeaders = $this->processHeaders($headers);
 247  
 248          $streamInterface = new StreamResponse('php://memory', 'rw');
 249          $streamInterface->write($body);
 250  
 251          return new Response($streamInterface, $statusCode, $verifiedHeaders);
 252      }
 253  
 254      /**
 255       * Method to check if http transport stream available for use
 256       *
 257       * @return  boolean  True if available else false
 258       *
 259       * @since   1.0
 260       */
 261  	public static function isSupported()
 262      {
 263          return \function_exists('fopen') && \is_callable('fopen') && ini_get('allow_url_fopen');
 264      }
 265  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer