Source for file curl.php

Documentation is available at curl.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  HTTP
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM'or die;
  11.  
  12. /**
  13.  * HTTP transport class for using cURL.
  14.  *
  15.  * @package     Joomla.Platform
  16.  * @subpackage  HTTP
  17.  * @since       11.3
  18.  */
  19. class JHttpTransportCurl implements JHttpTransport
  20. {
  21.     /**
  22.      * @var    JRegistry  The client options.
  23.      * @since  11.3
  24.      */
  25.     protected $options;
  26.  
  27.     /**
  28.      * Constructor. CURLOPT_FOLLOWLOCATION must be disabled when open_basedir or safe_mode are enabled.
  29.      *
  30.      * @param   JRegistry  $options  Client options object.
  31.      *
  32.      * @see     http://www.php.net/manual/en/function.curl-setopt.php
  33.      * @since   11.3
  34.      * @throws  RuntimeException
  35.      */
  36.     public function __construct(JRegistry $options)
  37.     {
  38.         if (!function_exists('curl_init'|| !is_callable('curl_init'))
  39.         {
  40.             throw new RuntimeException('Cannot use a cURL transport when curl_init() is not available.');
  41.         }
  42.  
  43.         $this->options = $options;
  44.     }
  45.  
  46.     /**
  47.      * Send a request to the server and return a JHttpResponse object with the response.
  48.      *
  49.      * @param   string   $method     The HTTP method for sending the request.
  50.      * @param   JUri     $uri        The URI to the resource to request.
  51.      * @param   mixed    $data       Either an associative array or a string to be sent with the request.
  52.      * @param   array    $headers    An array of request headers to send with the request.
  53.      * @param   integer  $timeout    Read timeout in seconds.
  54.      * @param   string   $userAgent  The optional user agent string to send with the request.
  55.      *
  56.      * @return  JHttpResponse 
  57.      *
  58.      * @since   11.3
  59.      * @throws  RuntimeException
  60.      */
  61.     public function request($methodJUri $uri$data nullarray $headers null$timeout null$userAgent null)
  62.     {
  63.         // Setup the cURL handle.
  64.         $ch curl_init();
  65.  
  66.         // Set the request method.
  67.         $options[CURLOPT_CUSTOMREQUESTstrtoupper($method);
  68.  
  69.         // Don't wait for body when $method is HEAD
  70.         $options[CURLOPT_NOBODY($method === 'HEAD');
  71.  
  72.         // Initialize the certificate store
  73.         $options[CURLOPT_CAINFO$this->options->get('curl.certpath'__DIR__ . '/cacert.pem');
  74.  
  75.         // If data exists let's encode it and make sure our Content-type header is set.
  76.         if (isset($data))
  77.         {
  78.             // If the data is a scalar value simply add it to the cURL post fields.
  79.             if (is_scalar($data|| (isset($headers['Content-Type']&& strpos($headers['Content-Type']'multipart/form-data'=== 0))
  80.             {
  81.                 $options[CURLOPT_POSTFIELDS$data;
  82.             }
  83.  
  84.             // Otherwise we need to encode the value first.
  85.             else
  86.             {
  87.                 $options[CURLOPT_POSTFIELDShttp_build_query($data);
  88.             }
  89.  
  90.             if (!isset($headers['Content-Type']))
  91.             {
  92.                 $headers['Content-Type''application/x-www-form-urlencoded; charset=utf-8';
  93.             }
  94.  
  95.             // Add the relevant headers.
  96.             if (is_scalar($options[CURLOPT_POSTFIELDS]))
  97.             {
  98.                 $headers['Content-Length'strlen($options[CURLOPT_POSTFIELDS]);
  99.             }
  100.         }
  101.  
  102.         // Build the headers string for the request.
  103.         $headerArray array();
  104.  
  105.         if (isset($headers))
  106.         {
  107.             foreach ($headers as $key => $value)
  108.             {
  109.                 $headerArray[$key ': ' $value;
  110.             }
  111.  
  112.             // Add the headers string into the stream context options array.
  113.             $options[CURLOPT_HTTPHEADER$headerArray;
  114.         }
  115.  
  116.         // If an explicit timeout is given user it.
  117.         if (isset($timeout))
  118.         {
  119.             $options[CURLOPT_TIMEOUT= (int) $timeout;
  120.             $options[CURLOPT_CONNECTTIMEOUT= (int) $timeout;
  121.         }
  122.  
  123.         // If an explicit user agent is given use it.
  124.         if (isset($userAgent))
  125.         {
  126.             $options[CURLOPT_USERAGENT$userAgent;
  127.         }
  128.  
  129.         // Set the request URL.
  130.         $options[CURLOPT_URL= (string) $uri;
  131.  
  132.         // We want our headers. :-)
  133.         $options[CURLOPT_HEADERtrue;
  134.  
  135.         // Return it... echoing it would be tacky.
  136.         $options[CURLOPT_RETURNTRANSFERtrue;
  137.  
  138.         // Override the Expect header to prevent cURL from confusing itself in its own stupidity.
  139.         // Link: http://the-stickman.com/web-development/php-and-curl-disabling-100-continue-header/
  140.         $options[CURLOPT_HTTPHEADER]['Expect:';
  141.  
  142.         // Follow redirects.
  143.         $options[CURLOPT_FOLLOWLOCATION= (bool) $this->options->get('follow_location'true);
  144.  
  145.         // Set the cURL options.
  146.         curl_setopt_array($ch$options);
  147.  
  148.         // Execute the request and close the connection.
  149.         $content curl_exec($ch);
  150.  
  151.         // Check if the content is a string. If it is not, it must be an error.
  152.         if (!is_string($content))
  153.         {
  154.             $message curl_error($ch);
  155.  
  156.             if (empty($message))
  157.             {
  158.                 // Error but nothing from cURL? Create our own
  159.                 $message 'No HTTP response received';
  160.             }
  161.  
  162.             throw new RuntimeException($message);
  163.         }
  164.  
  165.         // Get the request information.
  166.         $info curl_getinfo($ch);
  167.  
  168.         // Close the connection.
  169.         curl_close($ch);
  170.  
  171.         return $this->getResponse($content$info);
  172.     }
  173.  
  174.     /**
  175.      * Method to get a response object from a server response.
  176.      *
  177.      * @param   string  $content  The complete server response, including headers
  178.      *                             as a string if the response has no errors.
  179.      * @param   array   $info     The cURL request information.
  180.      *
  181.      * @return  JHttpResponse 
  182.      *
  183.      * @since   11.3
  184.      * @throws  UnexpectedValueException
  185.      */
  186.     protected function getResponse($content$info)
  187.     {
  188.         // Create the response object.
  189.         $return new JHttpResponse;
  190.  
  191.         // Get the number of redirects that occurred.
  192.         $redirects = isset($info['redirect_count']$info['redirect_count'0;
  193.  
  194.         /*
  195.          * Split the response into headers and body. If cURL encountered redirects, the headers for the redirected requests will
  196.          * also be included. So we split the response into header + body + the number of redirects and only use the last two
  197.          * sections which should be the last set of headers and the actual body.
  198.          */
  199.         $response explode("\r\n\r\n"$content$redirects);
  200.  
  201.         // Set the body for the response.
  202.         $return->body array_pop($response);
  203.  
  204.         // Get the last set of response headers as an array.
  205.         $headers explode("\r\n"array_pop($response));
  206.  
  207.         // Get the response code from the first offset of the response headers.
  208.         preg_match('/[0-9]{3}/'array_shift($headers)$matches);
  209.  
  210.         $code count($matches$matches[0null;
  211.  
  212.         if (is_numeric($code))
  213.         {
  214.             $return->code = (int) $code;
  215.         }
  216.  
  217.         // No valid response code was detected.
  218.         else
  219.         {
  220.             throw new UnexpectedValueException('No HTTP response code found.');
  221.         }
  222.  
  223.         // Add the response headers to the response object.
  224.         foreach ($headers as $header)
  225.         {
  226.             $pos strpos($header':');
  227.             $return->headers[trim(substr($header0$pos))trim(substr($header($pos 1)));
  228.         }
  229.  
  230.         return $return;
  231.     }
  232.  
  233.     /**
  234.      * Method to check if HTTP transport cURL is available for use
  235.      *
  236.      * @return boolean true if available, else false
  237.      *
  238.      * @since   12.1
  239.      */
  240.     public static function isSupported()
  241.     {
  242.         return function_exists('curl_version'&& curl_version();
  243.     }
  244. }

Documentation generated on Tue, 19 Nov 2013 14:57:41 +0100 by phpDocumentor 1.4.3