Zend_Http_Client_Adapter_Curl

An adapter class for Zend_Http_Client based on the curl extension.

Defined (1)

The class is defined in the following location(s).

/inc/VideoUploader/includes/Zend/Http/Client/Adapter/Curl.php  
  1. class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interface, Zend_Http_Client_Adapter_Stream 
  2. /** 
  3. * Parameters array 
  4. * @var array 
  5. */ 
  6. protected $_config = array(); 
  7.  
  8. /** 
  9. * What host/port are we connected to? 
  10. * @var array 
  11. */ 
  12. protected $_connected_to = array(null, null); 
  13.  
  14. /** 
  15. * The curl session handle 
  16. * @var resource|null 
  17. */ 
  18. protected $_curl = null; 
  19.  
  20. /** 
  21. * List of cURL options that should never be overwritten 
  22. * @var array 
  23. */ 
  24. protected $_invalidOverwritableCurlOptions; 
  25.  
  26. /** 
  27. * Response gotten from server 
  28. * @var string 
  29. */ 
  30. protected $_response = null; 
  31.  
  32. /** 
  33. * Stream for storing output 
  34. * @var resource 
  35. */ 
  36. protected $out_stream; 
  37.  
  38. /** 
  39. * Adapter constructor 
  40. * Config is set using setConfig() 
  41. * @return void 
  42. * @throws Zend_Http_Client_Adapter_Exception 
  43. */ 
  44. public function __construct() 
  45. if (!extension_loaded('curl')) { 
  46. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  47. throw new Zend_Http_Client_Adapter_Exception('cURL extension has to be loaded to use this Zend_Http_Client adapter.'); 
  48. $this->_invalidOverwritableCurlOptions = array( 
  49. CURLOPT_HTTPGET,  
  50. CURLOPT_POST,  
  51. CURLOPT_PUT,  
  52. CURLOPT_CUSTOMREQUEST,  
  53. CURLOPT_HEADER,  
  54. CURLOPT_RETURNTRANSFER,  
  55. CURLOPT_HTTPHEADER,  
  56. CURLOPT_POSTFIELDS,  
  57. CURLOPT_INFILE,  
  58. CURLOPT_INFILESIZE,  
  59. CURLOPT_PORT,  
  60. CURLOPT_MAXREDIRS,  
  61. CURLOPT_CONNECTTIMEOUT,  
  62. CURL_HTTP_VERSION_1_1,  
  63. CURL_HTTP_VERSION_1_0,  
  64. ); 
  65.  
  66. /** 
  67. * Set the configuration array for the adapter 
  68. * @throws Zend_Http_Client_Adapter_Exception 
  69. * @param Zend_Config | array $config 
  70. * @return Zend_Http_Client_Adapter_Curl 
  71. */ 
  72. public function setConfig($config = array()) 
  73. if ($config instanceof Zend_Config) { 
  74. $config = $config->toArray(); 
  75.  
  76. } elseif (! is_array($config)) { 
  77. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  78. throw new Zend_Http_Client_Adapter_Exception( 
  79. 'Array or Zend_Config object expected, got ' . gettype($config) 
  80. ); 
  81.  
  82. if(isset($config['proxy_user']) && isset($config['proxy_pass'])) { 
  83. $this->setCurlOption(CURLOPT_PROXYUSERPWD, $config['proxy_user'].":".$config['proxy_pass']); 
  84. unset($config['proxy_user'], $config['proxy_pass']); 
  85.  
  86. foreach ($config as $k => $v) { 
  87. $option = strtolower($k); 
  88. switch($option) { 
  89. case 'proxy_host': 
  90. $this->setCurlOption(CURLOPT_PROXY, $v); 
  91. break; 
  92. case 'proxy_port': 
  93. $this->setCurlOption(CURLOPT_PROXYPORT, $v); 
  94. break; 
  95. default: 
  96. $this->_config[$option] = $v; 
  97. break; 
  98.  
  99. return $this; 
  100.  
  101. /** 
  102. * Retrieve the array of all configuration options 
  103. * @return array 
  104. */ 
  105. public function getConfig() 
  106. return $this->_config; 
  107.  
  108. /** 
  109. * Direct setter for cURL adapter related options. 
  110. * @param string|int $option 
  111. * @param mixed $value 
  112. * @return Zend_Http_Adapter_Curl 
  113. */ 
  114. public function setCurlOption($option, $value) 
  115. if (!isset($this->_config['curloptions'])) { 
  116. $this->_config['curloptions'] = array(); 
  117. $this->_config['curloptions'][$option] = $value; 
  118. return $this; 
  119.  
  120. /** 
  121. * Initialize curl 
  122. * @param string $host 
  123. * @param int $port 
  124. * @param boolean $secure 
  125. * @return void 
  126. * @throws Zend_Http_Client_Adapter_Exception if unable to connect 
  127. */ 
  128. public function connect($host, $port = 80, $secure = false) 
  129. // If we're already connected, disconnect first 
  130. if ($this->_curl) { 
  131. $this->close(); 
  132.  
  133. // If we are connected to a different server or port, disconnect first 
  134. if ($this->_curl 
  135. && is_array($this->_connected_to) 
  136. && ($this->_connected_to[0] != $host 
  137. || $this->_connected_to[1] != $port) 
  138. ) { 
  139. $this->close(); 
  140.  
  141. // Do the actual connection 
  142. $this->_curl = curl_init(); 
  143. if ($port != 80) { 
  144. curl_setopt($this->_curl, CURLOPT_PORT, intval($port)); 
  145.  
  146. // Set timeout 
  147. curl_setopt($this->_curl, CURLOPT_CONNECTTIMEOUT, $this->_config['timeout']); 
  148.  
  149. // Set Max redirects 
  150. curl_setopt($this->_curl, CURLOPT_MAXREDIRS, $this->_config['maxredirects']); 
  151.  
  152. if (!$this->_curl) { 
  153. $this->close(); 
  154.  
  155. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  156. throw new Zend_Http_Client_Adapter_Exception('Unable to Connect to ' . $host . ':' . $port); 
  157.  
  158. if ($secure !== false) { 
  159. // Behave the same like Zend_Http_Adapter_Socket on SSL options. 
  160. if (isset($this->_config['sslcert'])) { 
  161. curl_setopt($this->_curl, CURLOPT_SSLCERT, $this->_config['sslcert']); 
  162. if (isset($this->_config['sslpassphrase'])) { 
  163. curl_setopt($this->_curl, CURLOPT_SSLCERTPASSWD, $this->_config['sslpassphrase']); 
  164.  
  165. // Update connected_to 
  166. $this->_connected_to = array($host, $port); 
  167.  
  168. /** 
  169. * Send request to the remote server 
  170. * @param string $method 
  171. * @param Zend_Uri_Http $uri 
  172. * @param float $http_ver 
  173. * @param array $headers 
  174. * @param string $body 
  175. * @return string $request 
  176. * @throws Zend_Http_Client_Adapter_Exception If connection fails, connected to wrong host, no PUT file defined, unsupported method, or unsupported cURL option 
  177. */ 
  178. public function write($method, $uri, $httpVersion = 1.1, $headers = array(), $body = '') 
  179. // Make sure we're properly connected 
  180. if (!$this->_curl) { 
  181. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  182. throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected"); 
  183.  
  184. if ($this->_connected_to[0] != $uri->getHost() || $this->_connected_to[1] != $uri->getPort()) { 
  185. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  186. throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host"); 
  187.  
  188. // set URL 
  189. curl_setopt($this->_curl, CURLOPT_URL, $uri->__toString()); 
  190.  
  191. // ensure correct curl call 
  192. $curlValue = true; 
  193. switch ($method) { 
  194. case Zend_Http_Client::GET: 
  195. $curlMethod = CURLOPT_HTTPGET; 
  196. break; 
  197.  
  198. case Zend_Http_Client::POST: 
  199. $curlMethod = CURLOPT_POST; 
  200. break; 
  201.  
  202. case Zend_Http_Client::PUT: 
  203. // There are two different types of PUT request, either a Raw Data string has been set 
  204. // or CURLOPT_INFILE and CURLOPT_INFILESIZE are used. 
  205. if(is_resource($body)) { 
  206. $this->_config['curloptions'][CURLOPT_INFILE] = $body; 
  207. if (isset($this->_config['curloptions'][CURLOPT_INFILE])) { 
  208. // Now we will probably already have Content-Length set, so that we have to delete it 
  209. // from $headers at this point: 
  210. foreach ($headers AS $k => $header) { 
  211. if (preg_match('/Content-Length:\s*(\d+)/i', $header, $m)) { 
  212. if(is_resource($body)) { 
  213. $this->_config['curloptions'][CURLOPT_INFILESIZE] = (int)$m[1]; 
  214. unset($headers[$k]); 
  215.  
  216. if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) { 
  217. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  218. throw new Zend_Http_Client_Adapter_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE."); 
  219.  
  220. if(is_resource($body)) { 
  221. $body = ''; 
  222.  
  223. $curlMethod = CURLOPT_PUT; 
  224. } else { 
  225. $curlMethod = CURLOPT_CUSTOMREQUEST; 
  226. $curlValue = "PUT"; 
  227. break; 
  228.  
  229. case Zend_Http_Client::DELETE: 
  230. $curlMethod = CURLOPT_CUSTOMREQUEST; 
  231. $curlValue = "DELETE"; 
  232. break; 
  233.  
  234. case Zend_Http_Client::OPTIONS: 
  235. $curlMethod = CURLOPT_CUSTOMREQUEST; 
  236. $curlValue = "OPTIONS"; 
  237. break; 
  238.  
  239. case Zend_Http_Client::TRACE: 
  240. $curlMethod = CURLOPT_CUSTOMREQUEST; 
  241. $curlValue = "TRACE"; 
  242. break; 
  243.  
  244. case Zend_Http_Client::HEAD: 
  245. $curlMethod = CURLOPT_CUSTOMREQUEST; 
  246. $curlValue = "HEAD"; 
  247. break; 
  248.  
  249. default: 
  250. // For now, through an exception for unsupported request methods 
  251. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  252. throw new Zend_Http_Client_Adapter_Exception("Method currently not supported"); 
  253.  
  254. if(is_resource($body) && $curlMethod != CURLOPT_PUT) { 
  255. require_once 'Zend/Http/Client/Adapter/Exception.php'; 
  256. throw new Zend_Http_Client_Adapter_Exception("Streaming requests are allowed only with PUT"); 
  257.  
  258. // get http version to use 
  259. $curlHttp = ($httpVersion == 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0; 
  260.  
  261. // mark as HTTP request and set HTTP method 
  262. curl_setopt($this->_curl, $curlHttp, true); 
  263. curl_setopt($this->_curl, $curlMethod, $curlValue); 
  264.  
  265. if($this->out_stream) { 
  266. // headers will be read into the response 
  267. curl_setopt($this->_curl, CURLOPT_HEADER, false); 
  268. curl_setopt($this->_curl, CURLOPT_HEADERFUNCTION, array($this, "readHeader")); 
  269. // and data will be written into the file 
  270. curl_setopt($this->_curl, CURLOPT_FILE, $this->out_stream); 
  271. } else { 
  272. // ensure headers are also returned 
  273. curl_setopt($this->_curl, CURLOPT_HEADER, true); 
  274.  
  275. // ensure actual response is returned 
  276. curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true); 
  277.  
  278. // set additional headers 
  279. $headers['Accept'] = ''; 
  280. curl_setopt($this->_curl, CURLOPT_HTTPHEADER, $headers); 
  281.  
  282. /** 
  283. * Make sure POSTFIELDS is set after $curlMethod is set: 
  284. * @link http://de2.php.net/manual/en/function.curl-setopt.php#81161 
  285. */ 
  286. if ($method == Zend_Http_Client::POST) { 
  287. curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); 
  288. } elseif ($curlMethod == CURLOPT_PUT) { 
  289. // this covers a PUT by file-handle: 
  290. // Make the setting of this options explicit (rather than setting it through the loop following a bit lower) 
  291. // to group common functionality together. 
  292. curl_setopt($this->_curl, CURLOPT_INFILE, $this->_config['curloptions'][CURLOPT_INFILE]); 
  293. curl_setopt($this->_curl, CURLOPT_INFILESIZE, $this->_config['curloptions'][CURLOPT_INFILESIZE]); 
  294. unset($this->_config['curloptions'][CURLOPT_INFILE]); 
  295. unset($this->_config['curloptions'][CURLOPT_INFILESIZE]); 
  296. } elseif ($method == Zend_Http_Client::PUT) { 
  297. // This is a PUT by a setRawData string, not by file-handle 
  298. curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); 
  299. } elseif ($method == Zend_Http_Client::DELETE) { 
  300. // This is a DELETE by a setRawData string 
  301. curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); 
  302.  
  303. // set additional curl options 
  304. if (isset($this->_config['curloptions'])) { 
  305. foreach ((array)$this->_config['curloptions'] as $k => $v) { 
  306. if (!in_array($k, $this->_invalidOverwritableCurlOptions)) { 
  307. if (curl_setopt($this->_curl, $k, $v) == false) { 
  308. require_once 'Zend/Http/Client/Exception.php'; 
  309. throw new Zend_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k)); 
  310.  
  311. // send the request 
  312. $response = curl_exec($this->_curl); 
  313.  
  314. // if we used streaming, headers are already there 
  315. if(!is_resource($this->out_stream)) { 
  316. $this->_response = $response; 
  317.  
  318. $request = curl_getinfo($this->_curl, CURLINFO_HEADER_OUT); 
  319. $request .= $body; 
  320.  
  321. if (empty($this->_response)) { 
  322. require_once 'Zend/Http/Client/Exception.php'; 
  323. throw new Zend_Http_Client_Exception("Error in cURL request: " . curl_error($this->_curl)); 
  324.  
  325. // cURL automatically decodes chunked-messages, this means we have to disallow the Zend_Http_Response to do it again 
  326. if (stripos($this->_response, "Transfer-Encoding: chunked\r\n")) { 
  327. $this->_response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $this->_response); 
  328.  
  329. // Eliminate multiple HTTP responses. 
  330. do { 
  331. $parts = preg_split('|(?:\r?\n) {2}|m', $this->_response, 2); 
  332. $again = false; 
  333.  
  334. if (isset($parts[1]) && preg_match("|^HTTP/1\.[01](.*?)\r\n|mi", $parts[1])) { 
  335. $this->_response = $parts[1]; 
  336. $again = true; 
  337. } while ($again); 
  338.  
  339. // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string: 
  340. if (stripos($this->_response, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) { 
  341. $this->_response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $this->_response); 
  342.  
  343. return $request; 
  344.  
  345. /** 
  346. * Return read response from server 
  347. * @return string 
  348. */ 
  349. public function read() 
  350. return $this->_response; 
  351.  
  352. /** 
  353. * Close the connection to the server 
  354. */ 
  355. public function close() 
  356. if(is_resource($this->_curl)) { 
  357. curl_close($this->_curl); 
  358. $this->_curl = null; 
  359. $this->_connected_to = array(null, null); 
  360.  
  361. /** 
  362. * Get cUrl Handle 
  363. * @return resource 
  364. */ 
  365. public function getHandle() 
  366. return $this->_curl; 
  367.  
  368. /** 
  369. * Set output stream for the response 
  370. * @param resource $stream 
  371. * @return Zend_Http_Client_Adapter_Socket 
  372. */ 
  373. public function setOutputStream($stream) 
  374. $this->out_stream = $stream; 
  375. return $this; 
  376.  
  377. /** 
  378. * Header reader function for CURL 
  379. * @param resource $curl 
  380. * @param string $header 
  381. * @return int 
  382. */ 
  383. public function readHeader($curl, $header) 
  384. $this->_response .= $header; 
  385. return strlen($header);