PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/canoo/tests/testcases/level0/2.8.1/plug-ins/www/admin/plugins/oxMarket/library/Zend/Http/Client/Adapter/Curl.php

https://github.com/orchestra-io/sample-openx
PHP | 330 lines | 163 code | 36 blank | 131 comment | 52 complexity | 9bd183de16ae11446d5b0fc3f90cca41 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Http
  17. * @subpackage Client_Adapter
  18. * @version $Id: Curl.php 34116 2009-03-23 10:41:43Z lukasz.wikierski $
  19. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  20. * @license http://framework.zend.com/license/new-bsd New BSD License
  21. */
  22. require_once 'Zend/Uri/Http.php';
  23. require_once 'Zend/Http/Client/Adapter/Interface.php';
  24. require_once 'Zend/Http/Client/Adapter/Exception.php';
  25. /**
  26. * An adapter class for Zend_Http_Client based on the curl extension.
  27. * Curl requires libcurl. See for full requirements the PHP manual: http://php.net/curl
  28. *
  29. * @category Zend
  30. * @package Zend_Http
  31. * @subpackage Client_Adapter
  32. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interface
  36. {
  37. /**
  38. * The curl session handle
  39. *
  40. * @var resource|null
  41. */
  42. protected $curl = null;
  43. /**
  44. * What host/port are we connected to?
  45. *
  46. * @var array
  47. */
  48. protected $connected_to = array(null, null);
  49. /**
  50. * Parameters array
  51. *
  52. * @var array
  53. */
  54. protected $config = array();
  55. /**
  56. * Response gotten from server
  57. *
  58. * @var string
  59. */
  60. protected $response = null;
  61. /**
  62. * Adapter constructor, currently empty. Config is set using setConfig()
  63. * @throws Zend_Http_Client_Adapter_Exception
  64. */
  65. public function __construct()
  66. {
  67. if(extension_loaded('curl') === false) {
  68. throw new Zend_Http_Client_Adapter_Exception('cURL extension has to be loaded to use this Zend_Http_Client adapter.');
  69. }
  70. }
  71. /**
  72. * Set the configuration array for the adapter
  73. *
  74. * @throws Zend_Http_Client_Adapter_Exception
  75. * @param array $config
  76. */
  77. public function setConfig($config = array())
  78. {
  79. if (! is_array($config)) {
  80. throw new Zend_Http_Client_Adapter_Exception('Http Adapter configuration expects an array, ' . gettype($config) . ' recieved.');
  81. }
  82. foreach ($config as $k => $v) {
  83. $this->config[strtolower($k)] = $v;
  84. }
  85. }
  86. /**
  87. * Direct setter for cURL adapter related options.
  88. *
  89. * @param string|int $option
  90. * @param mixed $value
  91. * @return Zend_Http_Adapter_Curl
  92. */
  93. public function setCurlOption($option, $value)
  94. {
  95. if(!isset($this->config['curloptions'])) {
  96. $this->config['curloptions'] = array();
  97. }
  98. $this->config['curloptions'][$option] = $value;
  99. return $this;
  100. }
  101. /**
  102. * Initialize curl
  103. *
  104. * @param string $host
  105. * @param int $port
  106. * @param boolean $secure
  107. */
  108. public function connect($host, $port = 80, $secure = false)
  109. {
  110. // If we're already connected, disconnect first
  111. if ($this->curl) $this->close();
  112. // If we are connected to a different server or port, disconnect first
  113. if ($this->curl && is_array($this->connected_to) &&
  114. ($this->connected_to[0] != $host || $this->connected_to[1] != $port))
  115. $this->close();
  116. // Do the actual connection
  117. $this->curl = curl_init();
  118. if ($port != 80) {
  119. curl_setopt($this->curl, CURLOPT_PORT, intval($port));
  120. }
  121. // Set timeout
  122. curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->config['timeout']);
  123. // Set Max redirects
  124. curl_setopt($this->curl, CURLOPT_MAXREDIRS, $this->config['maxredirects']);
  125. if (! $this->curl) {
  126. $this->close();
  127. throw new Zend_Http_Client_Adapter_Exception('Unable to Connect to ' .
  128. $host . ':' . $port);
  129. }
  130. if($secure == true) {
  131. // Behave the same like Zend_Http_Adapter_Socket on SSL options.
  132. if($this->config['sslcert'] != null) {
  133. curl_setopt($this->curl, CURLOPT_SSLCERT, $this->config['sslcert']);
  134. }
  135. if($this->config['sslpassphrase'] !== null) {
  136. curl_setopt($this->curl, CURLOPT_SSLCERTPASSWD, $this->config['sslpassphrase']);
  137. }
  138. }
  139. // Update connected_to
  140. $this->connected_to = array($host, $port);
  141. }
  142. /**
  143. * Send request to the remote server
  144. *
  145. * @param string $method
  146. * @param Zend_Uri_Http $uri
  147. * @param float $http_ver
  148. * @param array $headers
  149. * @param string $body
  150. * @return string $request
  151. */
  152. public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
  153. {
  154. $invalidOverwritableCurlOptions = array(
  155. CURLOPT_HTTPGET, CURLOPT_POST, CURLOPT_PUT, CURLOPT_CUSTOMREQUEST, CURLOPT_HEADER,
  156. CURLOPT_RETURNTRANSFER, CURLOPT_HTTPHEADER, CURLOPT_POSTFIELDS, CURLOPT_INFILE,
  157. CURLOPT_INFILESIZE, CURLOPT_PORT, CURLOPT_MAXREDIRS, CURLOPT_TIMEOUT,
  158. CURL_HTTP_VERSION_1_1, CURL_HTTP_VERSION_1_0
  159. );
  160. // set URL
  161. curl_setopt($this->curl, CURLOPT_URL, $uri->__toString());
  162. // Make sure we're properly connected
  163. if (! $this->curl)
  164. throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected");
  165. if ($this->connected_to[0] != $uri->getHost() || $this->connected_to[1] != $uri->getPort())
  166. throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host");
  167. // ensure correct curl call
  168. $curlValue = true;
  169. if ($method == Zend_Http_Client::GET) {
  170. $curlMethod = CURLOPT_HTTPGET;
  171. } elseif ($method == Zend_Http_Client::POST) {
  172. $curlMethod = CURLOPT_POST;
  173. } elseif($method == Zend_Http_Client::PUT) {
  174. // There are two different types of PUT request, either a Raw Data string has been set
  175. // or CURLOPT_INFILE and CURLOPT_INFILESIZE are used.
  176. if(isset($this->config['curloptions'][CURLOPT_INFILE])) {
  177. if(!isset($this->config['curloptions'][CURLOPT_INFILESIZE])) {
  178. throw new Zend_Http_Client_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE.");
  179. }
  180. // Now we will probably already have Content-Length set, so that we have to delete it
  181. // from $headers at this point:
  182. foreach($headers AS $k => $header) {
  183. if(stristr($header, "Content-Length:") !== false) {
  184. unset($headers[$k]);
  185. }
  186. }
  187. $curlMethod = CURLOPT_PUT;
  188. } else {
  189. $curlMethod = CURLOPT_CUSTOMREQUEST;
  190. $curlValue = "PUT";
  191. }
  192. } elseif($method == Zend_Http_Client::DELETE) {
  193. $curlMethod = CURLOPT_CUSTOMREQUEST;
  194. $curlValue = "DELETE";
  195. } elseif($method == Zend_Http_Client::OPTIONS) {
  196. $curlMethod = CURLOPT_CUSTOMREQUEST;
  197. $curlValue = "OPTIONS";
  198. } elseif($method == Zend_Http_Client::TRACE) {
  199. $curlMethod = CURLOPT_CUSTOMREQUEST;
  200. $curlValue = "TRACE";
  201. } else {
  202. // For now, through an exception for unsupported request methods
  203. throw new Zend_Http_Client_Adapter_Exception("Method currently not supported");
  204. }
  205. // get http version to use
  206. $curlHttp = ($http_ver = 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
  207. curl_setopt($this->curl, $curlMethod, $curlValue);
  208. curl_setopt($this->curl, $curlHttp, true);
  209. // ensure headers are also returned
  210. curl_setopt($this->curl, CURLOPT_HEADER, true);
  211. // ensure actual response is returned
  212. curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
  213. // set additional headers
  214. $headers['Accept'] = "";
  215. curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers);
  216. /**
  217. * Make sure POSTFIELDS is set after $curlMethod is set:
  218. * @link http://de2.php.net/manual/en/function.curl-setopt.php#81161
  219. */
  220. if ($method == Zend_Http_Client::POST) {
  221. curl_setopt($this->curl, CURLOPT_POSTFIELDS, $body);
  222. } else if($curlMethod == CURLOPT_PUT) {
  223. // this covers a PUT by file-handle:
  224. // Make the setting of this options explicit (rather than setting it through the loop following a bit lower)
  225. // to group common functionality together.
  226. curl_setopt($this->curl, CURLOPT_INFILE, $this->config['curloptions'][CURLOPT_INFILE]);
  227. curl_setopt($this->curl, CURLOPT_INFILESIZE, $this->config['curloptions'][CURLOPT_INFILESIZE]);
  228. unset($this->config['curloptions'][CURLOPT_INFILE]);
  229. unset($this->config['curloptions'][CURLOPT_INFILESIZE]);
  230. } else if($method == Zend_Http_Client::PUT) {
  231. // This is a PUT by a setRawData string, not by file-handle
  232. curl_setopt($this->curl, CURLOPT_POSTFIELDS, $body);
  233. }
  234. // set additional curl options
  235. if(isset($this->config['curloptions'])) {
  236. foreach((array)$this->config['curloptions'] AS $k => $v) {
  237. if(!in_array($k, $invalidOverwritableCurlOptions)) {
  238. if(curl_setopt($this->curl, $k, $v) == false) {
  239. throw new Zend_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k));
  240. }
  241. }
  242. }
  243. }
  244. // send the request
  245. $this->response = curl_exec($this->curl);
  246. $request = curl_getinfo($this->curl, CURLINFO_HEADER_OUT);
  247. $request .= $body;
  248. if(empty($this->response)) {
  249. throw new Zend_Http_Client_Exception("Error in cURL request: ".curl_error($this->curl));
  250. }
  251. // cURL automatically decodes chunked-messages, this means we have to disallow the Zend_Http_Response to do it again
  252. if(stripos($this->response, "Transfer-Encoding: chunked\r\n")) {
  253. $this->response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $this->response);
  254. }
  255. // TODO: Probably the pattern for multiple handshake requests is always the same, several HTTP codes in the response. Use that information?
  256. // cURL automactically handles Expect: 100-continue; and its responses. Delete the HTTP 100 CONTINUE from a response
  257. // because it messes up Zend_Http_Response parsing
  258. if(stripos($this->response, "HTTP/1.1 100 Continue\r\n\r\n") !== false) {
  259. $this->response = str_ireplace("HTTP/1.1 100 Continue\r\n\r\n", '', $this->response);
  260. }
  261. // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string:
  262. if(stripos($this->response, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) {
  263. $this->response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $this->response);
  264. }
  265. return $request;
  266. }
  267. /**
  268. * Return read response from server
  269. *
  270. * @return string
  271. */
  272. public function read()
  273. {
  274. return $this->response;
  275. }
  276. /**
  277. * Close the connection to the server
  278. *
  279. */
  280. public function close()
  281. {
  282. curl_close($this->curl);
  283. $this->curl = null;
  284. $this->connected_to = array(null, null);
  285. }
  286. /**
  287. * Destructor: make sure curl is disconnected
  288. *
  289. */
  290. public function __destruct()
  291. {
  292. if ($this->curl) $this->close();
  293. }
  294. }