[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Zend Framework 5 * 6 * LICENSE 7 * 8 * This source file is subject to the new BSD license that is bundled 9 * with this package in the file LICENSE.txt. 10 * It is also available through the world-wide-web at this URL: 11 * http://framework.zend.com/license/new-bsd 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to [email protected] so we can send you a copy immediately. 15 * 16 * @category Zend 17 * @package Zend_Http 18 * @subpackage Client_Adapter 19 * @version $Id$ 20 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 21 * @license http://framework.zend.com/license/new-bsd New BSD License 22 */ 23 24 /** 25 * @see Zend_Uri_Http 26 */ 27 require_once 'Zend/Uri/Http.php'; 28 29 /** 30 * @see Zend_Http_Client_Adapter_Interface 31 */ 32 require_once 'Zend/Http/Client/Adapter/Interface.php'; 33 /** 34 * @see Zend_Http_Client_Adapter_Stream 35 */ 36 require_once 'Zend/Http/Client/Adapter/Stream.php'; 37 38 /** 39 * An adapter class for Zend_Http_Client based on the curl extension. 40 * Curl requires libcurl. See for full requirements the PHP manual: http://php.net/curl 41 * 42 * @category Zend 43 * @package Zend_Http 44 * @subpackage Client_Adapter 45 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 46 * @license http://framework.zend.com/license/new-bsd New BSD License 47 */ 48 class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interface, Zend_Http_Client_Adapter_Stream 49 { 50 /** 51 * Parameters array 52 * 53 * @var array 54 */ 55 protected $_config = array(); 56 57 /** 58 * What host/port are we connected to? 59 * 60 * @var array 61 */ 62 protected $_connected_to = array(null, null); 63 64 /** 65 * The curl session handle 66 * 67 * @var resource|null 68 */ 69 protected $_curl = null; 70 71 /** 72 * List of cURL options that should never be overwritten 73 * 74 * @var array 75 */ 76 protected $_invalidOverwritableCurlOptions; 77 78 /** 79 * Response gotten from server 80 * 81 * @var string 82 */ 83 protected $_response = null; 84 85 /** 86 * Stream for storing output 87 * 88 * @var resource 89 */ 90 protected $out_stream; 91 92 /** 93 * Adapter constructor 94 * 95 * Config is set using setConfig() 96 * 97 * @return void 98 * @throws Zend_Http_Client_Adapter_Exception 99 */ 100 public function __construct() 101 { 102 if (!extension_loaded('curl')) { 103 require_once 'Zend/Http/Client/Adapter/Exception.php'; 104 throw new Zend_Http_Client_Adapter_Exception('cURL extension has to be loaded to use this Zend_Http_Client adapter.'); 105 } 106 $this->_invalidOverwritableCurlOptions = array( 107 CURLOPT_HTTPGET, 108 CURLOPT_POST, 109 CURLOPT_PUT, 110 CURLOPT_CUSTOMREQUEST, 111 CURLOPT_HEADER, 112 CURLOPT_RETURNTRANSFER, 113 CURLOPT_HTTPHEADER, 114 CURLOPT_POSTFIELDS, 115 CURLOPT_INFILE, 116 CURLOPT_INFILESIZE, 117 CURLOPT_PORT, 118 CURLOPT_MAXREDIRS, 119 CURLOPT_CONNECTTIMEOUT, 120 CURL_HTTP_VERSION_1_1, 121 CURL_HTTP_VERSION_1_0, 122 ); 123 } 124 125 /** 126 * Set the configuration array for the adapter 127 * 128 * @throws Zend_Http_Client_Adapter_Exception 129 * @param Zend_Config | array $config 130 * @return Zend_Http_Client_Adapter_Curl 131 */ 132 public function setConfig($config = array()) 133 { 134 if ($config instanceof Zend_Config) { 135 $config = $config->toArray(); 136 137 } elseif (! is_array($config)) { 138 require_once 'Zend/Http/Client/Adapter/Exception.php'; 139 throw new Zend_Http_Client_Adapter_Exception( 140 'Array or Zend_Config object expected, got ' . gettype($config) 141 ); 142 } 143 144 if(isset($config['proxy_user']) && isset($config['proxy_pass'])) { 145 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $config['proxy_user'].":".$config['proxy_pass']); 146 unset($config['proxy_user'], $config['proxy_pass']); 147 } 148 149 foreach ($config as $k => $v) { 150 $option = strtolower($k); 151 switch($option) { 152 case 'proxy_host': 153 $this->setCurlOption(CURLOPT_PROXY, $v); 154 break; 155 case 'proxy_port': 156 $this->setCurlOption(CURLOPT_PROXYPORT, $v); 157 break; 158 default: 159 $this->_config[$option] = $v; 160 break; 161 } 162 } 163 164 return $this; 165 } 166 167 /** 168 * Retrieve the array of all configuration options 169 * 170 * @return array 171 */ 172 public function getConfig() 173 { 174 return $this->_config; 175 } 176 177 /** 178 * Direct setter for cURL adapter related options. 179 * 180 * @param string|int $option 181 * @param mixed $value 182 * @return Zend_Http_Adapter_Curl 183 */ 184 public function setCurlOption($option, $value) 185 { 186 if (!isset($this->_config['curloptions'])) { 187 $this->_config['curloptions'] = array(); 188 } 189 $this->_config['curloptions'][$option] = $value; 190 return $this; 191 } 192 193 /** 194 * Initialize curl 195 * 196 * @param string $host 197 * @param int $port 198 * @param boolean $secure 199 * @return void 200 * @throws Zend_Http_Client_Adapter_Exception if unable to connect 201 */ 202 public function connect($host, $port = 80, $secure = false) 203 { 204 // If we're already connected, disconnect first 205 if ($this->_curl) { 206 $this->close(); 207 } 208 209 // If we are connected to a different server or port, disconnect first 210 if ($this->_curl 211 && is_array($this->_connected_to) 212 && ($this->_connected_to[0] != $host 213 || $this->_connected_to[1] != $port) 214 ) { 215 $this->close(); 216 } 217 218 // Do the actual connection 219 $this->_curl = curl_init(); 220 if ($port != 80) { 221 curl_setopt($this->_curl, CURLOPT_PORT, intval($port)); 222 } 223 224 // Set timeout 225 curl_setopt($this->_curl, CURLOPT_CONNECTTIMEOUT, $this->_config['timeout']); 226 227 // Set Max redirects 228 curl_setopt($this->_curl, CURLOPT_MAXREDIRS, $this->_config['maxredirects']); 229 230 if (!$this->_curl) { 231 $this->close(); 232 233 require_once 'Zend/Http/Client/Adapter/Exception.php'; 234 throw new Zend_Http_Client_Adapter_Exception('Unable to Connect to ' . $host . ':' . $port); 235 } 236 237 if ($secure !== false) { 238 // Behave the same like Zend_Http_Adapter_Socket on SSL options. 239 if (isset($this->_config['sslcert'])) { 240 curl_setopt($this->_curl, CURLOPT_SSLCERT, $this->_config['sslcert']); 241 } 242 if (isset($this->_config['sslpassphrase'])) { 243 curl_setopt($this->_curl, CURLOPT_SSLCERTPASSWD, $this->_config['sslpassphrase']); 244 } 245 } 246 247 // Update connected_to 248 $this->_connected_to = array($host, $port); 249 } 250 251 /** 252 * Send request to the remote server 253 * 254 * @param string $method 255 * @param Zend_Uri_Http $uri 256 * @param float $http_ver 257 * @param array $headers 258 * @param string $body 259 * @return string $request 260 * @throws Zend_Http_Client_Adapter_Exception If connection fails, connected to wrong host, no PUT file defined, unsupported method, or unsupported cURL option 261 */ 262 public function write($method, $uri, $httpVersion = 1.1, $headers = array(), $body = '') 263 { 264 // Make sure we're properly connected 265 if (!$this->_curl) { 266 require_once 'Zend/Http/Client/Adapter/Exception.php'; 267 throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected"); 268 } 269 270 if ($this->_connected_to[0] != $uri->getHost() || $this->_connected_to[1] != $uri->getPort()) { 271 require_once 'Zend/Http/Client/Adapter/Exception.php'; 272 throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host"); 273 } 274 275 // set URL 276 curl_setopt($this->_curl, CURLOPT_URL, $uri->__toString()); 277 278 // ensure correct curl call 279 $curlValue = true; 280 switch ($method) { 281 case Zend_Http_Client::GET: 282 $curlMethod = CURLOPT_HTTPGET; 283 break; 284 285 case Zend_Http_Client::POST: 286 $curlMethod = CURLOPT_POST; 287 break; 288 289 case Zend_Http_Client::PUT: 290 // There are two different types of PUT request, either a Raw Data string has been set 291 // or CURLOPT_INFILE and CURLOPT_INFILESIZE are used. 292 if(is_resource($body)) { 293 $this->_config['curloptions'][CURLOPT_INFILE] = $body; 294 } 295 if (isset($this->_config['curloptions'][CURLOPT_INFILE])) { 296 // Now we will probably already have Content-Length set, so that we have to delete it 297 // from $headers at this point: 298 foreach ($headers AS $k => $header) { 299 if (preg_match('/Content-Length:\s*(\d+)/i', $header, $m)) { 300 if(is_resource($body)) { 301 $this->_config['curloptions'][CURLOPT_INFILESIZE] = (int)$m[1]; 302 } 303 unset($headers[$k]); 304 } 305 } 306 307 if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) { 308 require_once 'Zend/Http/Client/Adapter/Exception.php'; 309 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."); 310 } 311 312 if(is_resource($body)) { 313 $body = ''; 314 } 315 316 $curlMethod = CURLOPT_PUT; 317 } else { 318 $curlMethod = CURLOPT_CUSTOMREQUEST; 319 $curlValue = "PUT"; 320 } 321 break; 322 323 case Zend_Http_Client::DELETE: 324 $curlMethod = CURLOPT_CUSTOMREQUEST; 325 $curlValue = "DELETE"; 326 break; 327 328 case Zend_Http_Client::OPTIONS: 329 $curlMethod = CURLOPT_CUSTOMREQUEST; 330 $curlValue = "OPTIONS"; 331 break; 332 333 case Zend_Http_Client::TRACE: 334 $curlMethod = CURLOPT_CUSTOMREQUEST; 335 $curlValue = "TRACE"; 336 break; 337 338 case Zend_Http_Client::HEAD: 339 $curlMethod = CURLOPT_CUSTOMREQUEST; 340 $curlValue = "HEAD"; 341 break; 342 343 default: 344 // For now, through an exception for unsupported request methods 345 require_once 'Zend/Http/Client/Adapter/Exception.php'; 346 throw new Zend_Http_Client_Adapter_Exception("Method currently not supported"); 347 } 348 349 if(is_resource($body) && $curlMethod != CURLOPT_PUT) { 350 require_once 'Zend/Http/Client/Adapter/Exception.php'; 351 throw new Zend_Http_Client_Adapter_Exception("Streaming requests are allowed only with PUT"); 352 } 353 354 // get http version to use 355 $curlHttp = ($httpVersion == 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0; 356 357 // mark as HTTP request and set HTTP method 358 curl_setopt($this->_curl, $curlHttp, true); 359 curl_setopt($this->_curl, $curlMethod, $curlValue); 360 361 if($this->out_stream) { 362 // headers will be read into the response 363 curl_setopt($this->_curl, CURLOPT_HEADER, false); 364 curl_setopt($this->_curl, CURLOPT_HEADERFUNCTION, array($this, "readHeader")); 365 // and data will be written into the file 366 curl_setopt($this->_curl, CURLOPT_FILE, $this->out_stream); 367 } else { 368 // ensure headers are also returned 369 curl_setopt($this->_curl, CURLOPT_HEADER, true); 370 371 // ensure actual response is returned 372 curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true); 373 } 374 375 // set additional headers 376 $headers['Accept'] = ''; 377 curl_setopt($this->_curl, CURLOPT_HTTPHEADER, $headers); 378 379 /** 380 * Make sure POSTFIELDS is set after $curlMethod is set: 381 * @link http://de2.php.net/manual/en/function.curl-setopt.php#81161 382 */ 383 if ($method == Zend_Http_Client::POST) { 384 curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); 385 } elseif ($curlMethod == CURLOPT_PUT) { 386 // this covers a PUT by file-handle: 387 // Make the setting of this options explicit (rather than setting it through the loop following a bit lower) 388 // to group common functionality together. 389 curl_setopt($this->_curl, CURLOPT_INFILE, $this->_config['curloptions'][CURLOPT_INFILE]); 390 curl_setopt($this->_curl, CURLOPT_INFILESIZE, $this->_config['curloptions'][CURLOPT_INFILESIZE]); 391 unset($this->_config['curloptions'][CURLOPT_INFILE]); 392 unset($this->_config['curloptions'][CURLOPT_INFILESIZE]); 393 } elseif ($method == Zend_Http_Client::PUT) { 394 // This is a PUT by a setRawData string, not by file-handle 395 curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); 396 } 397 398 // set additional curl options 399 if (isset($this->_config['curloptions'])) { 400 foreach ((array)$this->_config['curloptions'] as $k => $v) { 401 if (!in_array($k, $this->_invalidOverwritableCurlOptions)) { 402 if (curl_setopt($this->_curl, $k, $v) == false) { 403 require_once 'Zend/Http/Client/Exception.php'; 404 throw new Zend_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k)); 405 } 406 } 407 } 408 } 409 410 // send the request 411 $response = curl_exec($this->_curl); 412 413 // if we used streaming, headers are already there 414 if(!is_resource($this->out_stream)) { 415 $this->_response = $response; 416 } 417 418 $request = curl_getinfo($this->_curl, CURLINFO_HEADER_OUT); 419 $request .= $body; 420 421 if (empty($this->_response)) { 422 require_once 'Zend/Http/Client/Exception.php'; 423 throw new Zend_Http_Client_Exception("Error in cURL request: " . curl_error($this->_curl)); 424 } 425 426 // cURL automatically decodes chunked-messages, this means we have to disallow the Zend_Http_Response to do it again 427 if (stripos($this->_response, "Transfer-Encoding: chunked\r\n")) { 428 $this->_response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $this->_response); 429 } 430 431 // Eliminate multiple HTTP responses. 432 do { 433 $parts = preg_split('|(?:\r?\n){2}|m', $this->_response, 2); 434 $again = false; 435 436 if (isset($parts[1]) && preg_match("|^HTTP/1\.[01](.*?)\r\n|mi", $parts[1])) { 437 $this->_response = $parts[1]; 438 $again = true; 439 } 440 } while ($again); 441 442 // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string: 443 if (stripos($this->_response, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) { 444 $this->_response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $this->_response); 445 } 446 447 return $request; 448 } 449 450 /** 451 * Return read response from server 452 * 453 * @return string 454 */ 455 public function read() 456 { 457 return $this->_response; 458 } 459 460 /** 461 * Close the connection to the server 462 * 463 */ 464 public function close() 465 { 466 if(is_resource($this->_curl)) { 467 curl_close($this->_curl); 468 } 469 $this->_curl = null; 470 $this->_connected_to = array(null, null); 471 } 472 473 /** 474 * Get cUrl Handle 475 * 476 * @return resource 477 */ 478 public function getHandle() 479 { 480 return $this->_curl; 481 } 482 483 /** 484 * Set output stream for the response 485 * 486 * @param resource $stream 487 * @return Zend_Http_Client_Adapter_Socket 488 */ 489 public function setOutputStream($stream) 490 { 491 $this->out_stream = $stream; 492 return $this; 493 } 494 495 /** 496 * Header reader function for CURL 497 * 498 * @param resource $curl 499 * @param string $header 500 * @return int 501 */ 502 public function readHeader($curl, $header) 503 { 504 $this->_response .= $header; 505 return strlen($header); 506 } 507 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |