1<?php 2/** 3 * Copyright 2007-2016 Horde LLC (http://www.horde.org/) 4 * 5 * @author Chuck Hagenbuch <chuck@horde.org> 6 * @license http://www.horde.org/licenses/bsd BSD 7 * @category Horde 8 * @package Http 9 */ 10 11/** 12 * @author Chuck Hagenbuch <chuck@horde.org> 13 * @license http://www.horde.org/licenses/bsd BSD 14 * @category Horde 15 * @package Http 16 */ 17class Horde_Http_Request_Curl extends Horde_Http_Request_Base 18{ 19 /** 20 * Map of HTTP authentication schemes from Horde_Http constants to 21 * HTTP_AUTH constants. 22 * 23 * @var array 24 */ 25 protected $_httpAuthSchemes = array( 26 Horde_Http::AUTH_ANY => CURLAUTH_ANY, 27 Horde_Http::AUTH_BASIC => CURLAUTH_BASIC, 28 Horde_Http::AUTH_DIGEST => CURLAUTH_DIGEST, 29 Horde_Http::AUTH_GSSNEGOTIATE => CURLAUTH_GSSNEGOTIATE, 30 Horde_Http::AUTH_NTLM => CURLAUTH_NTLM, 31 ); 32 33 /** 34 * Constructor 35 * 36 * @throws Horde_Http_Exception 37 */ 38 public function __construct($args = array()) 39 { 40 if (!extension_loaded('curl')) { 41 throw new Horde_Http_Exception('The curl extension is not installed. See http://php.net/curl.installation'); 42 } 43 44 parent::__construct($args); 45 } 46 47 /** 48 * Send this HTTP request 49 * 50 * @throws Horde_Http_Exception 51 * @return Horde_Http_Response_Base 52 */ 53 public function send() 54 { 55 $curl = curl_init(); 56 curl_setopt($curl, CURLOPT_URL, (string)$this->uri); 57 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 58 curl_setopt($curl, CURLOPT_HEADER, true); 59 curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->method); 60 curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout); 61 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifyPeer); 62 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyPeer ? 2 : 0); 63 64 // User-Agent 65 curl_setopt($curl, CURLOPT_USERAGENT, $this->userAgent); 66 67 // Redirects 68 if ($this->redirects) { 69 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); 70 curl_setopt($curl, CURLOPT_MAXREDIRS, $this->redirects); 71 } else { 72 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); 73 curl_setopt($curl, CURLOPT_MAXREDIRS, 0); 74 } 75 76 $data = $this->data; 77 if (is_array($data)) { 78 // If we don't set POSTFIELDS to a string, and the first value 79 // begins with @, it will be treated as a filename, and the proper 80 // POST data isn't passed. 81 $data = http_build_query($data); 82 } 83 if ($data) { 84 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 85 } 86 87 // Proxy settings 88 if ($this->proxyServer) { 89 curl_setopt($curl, CURLOPT_PROXY, $this->proxyServer); 90 if ($this->proxyPort) { 91 curl_setopt($curl, CURLOPT_PROXYPORT, $this->proxyPort); 92 } 93 if ($this->proxyUsername && $this->proxyPassword) { 94 curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->proxyUsername . ':' . $this->proxyPassword); 95 curl_setopt($curl, CURLOPT_PROXYAUTH, $this->_httpAuthScheme($this->proxyAuthenticationScheme)); 96 } 97 if ($this->proxyType == Horde_Http::PROXY_SOCKS5) { 98 curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); 99 } else if ($this->proxyType != Horde_Http::PROXY_HTTP) { 100 throw new Horde_Http_Exception(sprintf('Proxy type %s not supported by this request type!', $this->proxyType)); 101 } 102 } 103 104 // Authentication settings 105 if ($this->username) { 106 curl_setopt($curl, CURLOPT_USERPWD, $this->username . ':' . $this->password); 107 curl_setopt($curl, CURLOPT_HTTPAUTH, $this->_httpAuthScheme($this->authenticationScheme)); 108 } 109 110 // Concatenate the headers 111 $hdr = array(); 112 $headers = $this->headers; 113 if (empty($headers['Expect'])) { 114 $headers['Expect'] = ''; 115 } 116 foreach ($headers as $header => $value) { 117 $hdr[] = $header . ': ' . $value; 118 } 119 120 curl_setopt($curl, CURLOPT_HTTPHEADER, $hdr); 121 122 $result = curl_exec($curl); 123 if ($result === false) { 124 throw new Horde_Http_Exception(curl_error($curl), curl_errno($curl)); 125 } 126 $info = curl_getinfo($curl); 127 return new Horde_Http_Response_Curl((string)$this->uri, $result, $info); 128 } 129 130 /** 131 * Translate a Horde_Http::AUTH_* constant to CURLAUTH_* 132 * 133 * @param const 134 * @throws Horde_Http_Exception 135 * @return const 136 */ 137 protected function _httpAuthScheme($httpAuthScheme) 138 { 139 if (!isset($this->_httpAuthSchemes[$httpAuthScheme])) { 140 throw new Horde_Http_Exception('Unsupported authentication scheme (' . $httpAuthScheme . ')'); 141 } 142 return $this->_httpAuthSchemes[$httpAuthScheme]; 143 } 144} 145