File indexing completed on 2025-01-19 05:21:14
0001 <?php 0002 0003 /** 0004 * Zend Framework 0005 * 0006 * LICENSE 0007 * 0008 * This source file is subject to the new BSD license that is bundled 0009 * with this package in the file LICENSE.txt. 0010 * It is also available through the world-wide-web at this URL: 0011 * http://framework.zend.com/license/new-bsd 0012 * If you did not receive a copy of the license and are unable to 0013 * obtain it through the world-wide-web, please send an email 0014 * to license@zend.com so we can send you a copy immediately. 0015 * 0016 * @category Zend 0017 * @package Zend_Http 0018 * @subpackage Client 0019 * @version $Id$ 0020 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0021 * @license http://framework.zend.com/license/new-bsd New BSD License 0022 */ 0023 0024 /** 0025 * @see Zend_Loader 0026 */ 0027 // require_once 'Zend/Loader.php'; 0028 0029 0030 /** 0031 * @see Zend_Uri 0032 */ 0033 // require_once 'Zend/Uri.php'; 0034 0035 0036 /** 0037 * @see Zend_Http_Client_Adapter_Interface 0038 */ 0039 // require_once 'Zend/Http/Client/Adapter/Interface.php'; 0040 0041 0042 /** 0043 * @see Zend_Http_Header_HeaderValue 0044 */ 0045 // require_once 'Zend/Http/Header/HeaderValue.php'; 0046 0047 0048 /** 0049 * @see Zend_Http_Response 0050 */ 0051 // require_once 'Zend/Http/Response.php'; 0052 0053 /** 0054 * @see Zend_Http_Response_Stream 0055 */ 0056 // require_once 'Zend/Http/Response/Stream.php'; 0057 0058 /** 0059 * Zend_Http_Client is an implementation of an HTTP client in PHP. The client 0060 * supports basic features like sending different HTTP requests and handling 0061 * redirections, as well as more advanced features like proxy settings, HTTP 0062 * authentication and cookie persistence (using a Zend_Http_CookieJar object) 0063 * 0064 * @todo Implement proxy settings 0065 * @category Zend 0066 * @package Zend_Http 0067 * @subpackage Client 0068 * @throws Zend_Http_Client_Exception 0069 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0070 * @license http://framework.zend.com/license/new-bsd New BSD License 0071 */ 0072 class Zend_Http_Client 0073 { 0074 /** 0075 * HTTP request methods 0076 */ 0077 const GET = 'GET'; 0078 const POST = 'POST'; 0079 const PUT = 'PUT'; 0080 const HEAD = 'HEAD'; 0081 const DELETE = 'DELETE'; 0082 const TRACE = 'TRACE'; 0083 const OPTIONS = 'OPTIONS'; 0084 const CONNECT = 'CONNECT'; 0085 const MERGE = 'MERGE'; 0086 const PATCH = 'PATCH'; 0087 0088 /** 0089 * Supported HTTP Authentication methods 0090 */ 0091 const AUTH_BASIC = 'basic'; 0092 //const AUTH_DIGEST = 'digest'; <-- not implemented yet 0093 0094 /** 0095 * HTTP protocol versions 0096 */ 0097 const HTTP_1 = '1.1'; 0098 const HTTP_0 = '1.0'; 0099 0100 /** 0101 * Content attributes 0102 */ 0103 const CONTENT_TYPE = 'Content-Type'; 0104 const CONTENT_LENGTH = 'Content-Length'; 0105 0106 /** 0107 * POST data encoding methods 0108 */ 0109 const ENC_URLENCODED = 'application/x-www-form-urlencoded'; 0110 const ENC_FORMDATA = 'multipart/form-data'; 0111 0112 /** 0113 * Value types for Body key/value pairs 0114 */ 0115 const VTYPE_SCALAR = 'SCALAR'; 0116 const VTYPE_FILE = 'FILE'; 0117 0118 /** 0119 * Configuration array, set using the constructor or using ::setConfig() 0120 * 0121 * @var array 0122 */ 0123 protected $config = array( 0124 'maxredirects' => 5, 0125 'strictredirects' => false, 0126 'useragent' => 'Zend_Http_Client', 0127 'timeout' => 10, 0128 'adapter' => 'Zend_Http_Client_Adapter_Socket', 0129 'httpversion' => self::HTTP_1, 0130 'keepalive' => false, 0131 'storeresponse' => true, 0132 'strict' => true, 0133 'output_stream' => false, 0134 'encodecookies' => true, 0135 'rfc3986_strict' => false 0136 ); 0137 0138 /** 0139 * The adapter used to perform the actual connection to the server 0140 * 0141 * @var Zend_Http_Client_Adapter_Interface 0142 */ 0143 protected $adapter = null; 0144 0145 /** 0146 * Request URI 0147 * 0148 * @var Zend_Uri_Http 0149 */ 0150 protected $uri = null; 0151 0152 /** 0153 * Associative array of request headers 0154 * 0155 * @var array 0156 */ 0157 protected $headers = array(); 0158 0159 /** 0160 * HTTP request method 0161 * 0162 * @var string 0163 */ 0164 protected $method = self::GET; 0165 0166 /** 0167 * Associative array of GET parameters 0168 * 0169 * @var array 0170 */ 0171 protected $paramsGet = array(); 0172 0173 /** 0174 * Associative array of POST parameters 0175 * 0176 * @var array 0177 */ 0178 protected $paramsPost = array(); 0179 0180 /** 0181 * Request body content type (for POST requests) 0182 * 0183 * @var string 0184 */ 0185 protected $enctype = null; 0186 0187 /** 0188 * The raw post data to send. Could be set by setRawData($data, $enctype). 0189 * 0190 * @var string 0191 */ 0192 protected $raw_post_data = null; 0193 0194 /** 0195 * HTTP Authentication settings 0196 * 0197 * Expected to be an associative array with this structure: 0198 * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic') 0199 * Where 'type' should be one of the supported authentication types (see the AUTH_* 0200 * constants), for example 'basic' or 'digest'. 0201 * 0202 * If null, no authentication will be used. 0203 * 0204 * @var array|null 0205 */ 0206 protected $auth; 0207 0208 /** 0209 * File upload arrays (used in POST requests) 0210 * 0211 * An associative array, where each element is of the format: 0212 * 'name' => array('filename.txt', 'text/plain', 'This is the actual file contents') 0213 * 0214 * @var array 0215 */ 0216 protected $files = array(); 0217 0218 /** 0219 * Ordered list of keys from key/value pair data to include in body 0220 * 0221 * An associative array, where each element is of the format: 0222 * '<field name>' => VTYPE_SCALAR | VTYPE_FILE 0223 * 0224 * @var array 0225 */ 0226 protected $body_field_order = array(); 0227 0228 /** 0229 * The client's cookie jar 0230 * 0231 * @var Zend_Http_CookieJar 0232 */ 0233 protected $cookiejar = null; 0234 0235 /** 0236 * The last HTTP request sent by the client, as string 0237 * 0238 * @var string 0239 */ 0240 protected $last_request = null; 0241 0242 /** 0243 * The last HTTP response received by the client 0244 * 0245 * @var Zend_Http_Response 0246 */ 0247 protected $last_response = null; 0248 0249 /** 0250 * Redirection counter 0251 * 0252 * @var int 0253 */ 0254 protected $redirectCounter = 0; 0255 0256 /** 0257 * Status for unmasking GET array params 0258 * 0259 * @var boolean 0260 */ 0261 protected $_unmaskStatus = false; 0262 0263 /** 0264 * Status if the http_build_query function escapes brackets 0265 * 0266 * @var boolean 0267 */ 0268 protected $_queryBracketsEscaped = true; 0269 0270 /** 0271 * Fileinfo magic database resource 0272 * 0273 * This variable is populated the first time _detectFileMimeType is called 0274 * and is then reused on every call to this method 0275 * 0276 * @var resource 0277 */ 0278 protected static $_fileInfoDb = null; 0279 0280 /** 0281 * Constructor method. Will create a new HTTP client. Accepts the target 0282 * URL and optionally configuration array. 0283 * 0284 * @param Zend_Uri_Http|string $uri 0285 * @param array $config Configuration key-value pairs. 0286 */ 0287 public function __construct($uri = null, $config = null) 0288 { 0289 if ($uri !== null) { 0290 $this->setUri($uri); 0291 } 0292 if ($config !== null) { 0293 $this->setConfig($config); 0294 } 0295 0296 $this->_queryBracketsEscaped = version_compare(phpversion(), '5.1.3', '>='); 0297 } 0298 0299 /** 0300 * Set the URI for the next request 0301 * 0302 * @param Zend_Uri_Http|string $uri 0303 * @return Zend_Http_Client 0304 * @throws Zend_Http_Client_Exception 0305 */ 0306 public function setUri($uri) 0307 { 0308 if ($uri instanceof Zend_Uri_Http) { 0309 // clone the URI in order to keep the passed parameter constant 0310 $uri = clone $uri; 0311 } elseif (is_string($uri)) { 0312 $uri = Zend_Uri::factory($uri); 0313 } 0314 0315 if (!$uri instanceof Zend_Uri_Http) { 0316 /** @see Zend_Http_Client_Exception */ 0317 // require_once 'Zend/Http/Client/Exception.php'; 0318 throw new Zend_Http_Client_Exception('Passed parameter is not a valid HTTP URI.'); 0319 } 0320 0321 // Set auth if username and password has been specified in the uri 0322 if ($uri->getUsername() && $uri->getPassword()) { 0323 $this->setAuth($uri->getUsername(), $uri->getPassword()); 0324 } 0325 0326 // We have no ports, set the defaults 0327 if (! $uri->getPort()) { 0328 $uri->setPort(($uri->getScheme() == 'https' ? 443 : 80)); 0329 } 0330 0331 $this->uri = $uri; 0332 0333 return $this; 0334 } 0335 0336 /** 0337 * Get the URI for the next request 0338 * 0339 * @param boolean $as_string If true, will return the URI as a string 0340 * @return Zend_Uri_Http|string 0341 */ 0342 public function getUri($as_string = false) 0343 { 0344 if ($as_string && $this->uri instanceof Zend_Uri_Http) { 0345 return $this->uri->__toString(); 0346 } else { 0347 return $this->uri; 0348 } 0349 } 0350 0351 /** 0352 * Set configuration parameters for this HTTP client 0353 * 0354 * @param Zend_Config | array $config 0355 * @return Zend_Http_Client 0356 * @throws Zend_Http_Client_Exception 0357 */ 0358 public function setConfig($config = array()) 0359 { 0360 if ($config instanceof Zend_Config) { 0361 $config = $config->toArray(); 0362 0363 } elseif (! is_array($config)) { 0364 /** @see Zend_Http_Client_Exception */ 0365 // require_once 'Zend/Http/Client/Exception.php'; 0366 throw new Zend_Http_Client_Exception('Array or Zend_Config object expected, got ' . gettype($config)); 0367 } 0368 0369 foreach ($config as $k => $v) { 0370 $this->config[strtolower($k)] = $v; 0371 } 0372 0373 // Pass configuration options to the adapter if it exists 0374 if ($this->adapter instanceof Zend_Http_Client_Adapter_Interface) { 0375 $this->adapter->setConfig($config); 0376 } 0377 0378 return $this; 0379 } 0380 0381 /** 0382 * Set the next request's method 0383 * 0384 * Validated the passed method and sets it. If we have files set for 0385 * POST requests, and the new method is not POST, the files are silently 0386 * dropped. 0387 * 0388 * @param string $method 0389 * @return Zend_Http_Client 0390 * @throws Zend_Http_Client_Exception 0391 */ 0392 public function setMethod($method = self::GET) 0393 { 0394 if (! preg_match('/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/', $method)) { 0395 // require_once 'Zend/Http/Client/Exception.php'; 0396 throw new Zend_Http_Client_Exception("'{$method}' is not a valid HTTP request method."); 0397 } 0398 0399 if (($method == self::POST 0400 || $method == self::PUT 0401 || $method == self::DELETE 0402 || $method == self::PATCH 0403 || $method == self::OPTIONS) 0404 && $this->enctype === null 0405 ) { 0406 $this->setEncType(self::ENC_URLENCODED); 0407 } 0408 0409 $this->method = $method; 0410 0411 return $this; 0412 } 0413 0414 /** 0415 * Set one or more request headers 0416 * 0417 * This function can be used in several ways to set the client's request 0418 * headers: 0419 * 1. By providing two parameters: $name as the header to set (e.g. 'Host') 0420 * and $value as it's value (e.g. 'www.example.com'). 0421 * 2. By providing a single header string as the only parameter 0422 * e.g. 'Host: www.example.com' 0423 * 3. By providing an array of headers as the first parameter 0424 * e.g. array('host' => 'www.example.com', 'x-foo: bar'). In This case 0425 * the function will call itself recursively for each array item. 0426 * 0427 * @param string|array $name Header name, full header string ('Header: value') 0428 * or an array of headers 0429 * @param mixed $value Header value or null 0430 * @return Zend_Http_Client 0431 * @throws Zend_Http_Client_Exception 0432 */ 0433 public function setHeaders($name, $value = null) 0434 { 0435 // If we got an array, go recursive! 0436 if (is_array($name)) { 0437 foreach ($name as $k => $v) { 0438 if (is_string($k)) { 0439 $this->setHeaders($k, $v); 0440 continue; 0441 } 0442 $this->setHeaders($v, null); 0443 } 0444 return $this; 0445 } 0446 0447 // Check if $name needs to be split 0448 if ($value === null && (strpos($name, ':') > 0)) { 0449 list($name, $value) = explode(':', $name, 2); 0450 } 0451 0452 // Make sure the name is valid if we are in strict mode 0453 if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) { 0454 // require_once 'Zend/Http/Client/Exception.php'; 0455 throw new Zend_Http_Client_Exception("{$name} is not a valid HTTP header name"); 0456 } 0457 0458 $normalized_name = strtolower($name); 0459 0460 // If $value is null or false, unset the header 0461 if ($value === null || $value === false) { 0462 unset($this->headers[$normalized_name]); 0463 return $this; 0464 } 0465 0466 // Validate value 0467 $this->_validateHeaderValue($value); 0468 0469 // Header names are stored lowercase internally. 0470 if (is_string($value)) { 0471 $value = trim($value); 0472 } 0473 $this->headers[$normalized_name] = array($name, $value); 0474 0475 return $this; 0476 } 0477 0478 /** 0479 * Get the value of a specific header 0480 * 0481 * Note that if the header has more than one value, an array 0482 * will be returned. 0483 * 0484 * @param string $key 0485 * @return string|array|null The header value or null if it is not set 0486 */ 0487 public function getHeader($key) 0488 { 0489 $key = strtolower($key); 0490 if (isset($this->headers[$key])) { 0491 return $this->headers[$key][1]; 0492 } else { 0493 return null; 0494 } 0495 } 0496 0497 /** 0498 * Set a GET parameter for the request. Wrapper around _setParameter 0499 * 0500 * @param string|array $name 0501 * @param string $value 0502 * @return Zend_Http_Client 0503 */ 0504 public function setParameterGet($name, $value = null) 0505 { 0506 if (is_array($name)) { 0507 foreach ($name as $k => $v) 0508 $this->_setParameter('GET', $k, $v); 0509 } else { 0510 $this->_setParameter('GET', $name, $value); 0511 } 0512 0513 return $this; 0514 } 0515 0516 /** 0517 * Set a POST parameter for the request. Wrapper around _setParameter 0518 * 0519 * @param string|array $name 0520 * @param string $value 0521 * @return Zend_Http_Client 0522 */ 0523 public function setParameterPost($name, $value = null) 0524 { 0525 if (is_array($name)) { 0526 foreach ($name as $k => $v) 0527 $this->_setParameter('POST', $k, $v); 0528 } else { 0529 $this->_setParameter('POST', $name, $value); 0530 } 0531 0532 return $this; 0533 } 0534 0535 /** 0536 * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost 0537 * 0538 * @param string $type GET or POST 0539 * @param string $name 0540 * @param string $value 0541 * @return null 0542 */ 0543 protected function _setParameter($type, $name, $value) 0544 { 0545 $parray = array(); 0546 $type = strtolower($type); 0547 switch ($type) { 0548 case 'get': 0549 $parray = &$this->paramsGet; 0550 break; 0551 case 'post': 0552 $parray = &$this->paramsPost; 0553 if ( $value === null ) { 0554 if (isset($this->body_field_order[$name])) 0555 unset($this->body_field_order[$name]); 0556 } else { 0557 $this->body_field_order[$name] = self::VTYPE_SCALAR; 0558 } 0559 break; 0560 } 0561 0562 if ($value === null) { 0563 if (isset($parray[$name])) unset($parray[$name]); 0564 } else { 0565 $parray[$name] = $value; 0566 } 0567 } 0568 0569 /** 0570 * Get the number of redirections done on the last request 0571 * 0572 * @return int 0573 */ 0574 public function getRedirectionsCount() 0575 { 0576 return $this->redirectCounter; 0577 } 0578 0579 /** 0580 * Set HTTP authentication parameters 0581 * 0582 * $type should be one of the supported types - see the self::AUTH_* 0583 * constants. 0584 * 0585 * To enable authentication: 0586 * <code> 0587 * $this->setAuth('shahar', 'secret', Zend_Http_Client::AUTH_BASIC); 0588 * </code> 0589 * 0590 * To disable authentication: 0591 * <code> 0592 * $this->setAuth(false); 0593 * </code> 0594 * 0595 * @see http://www.faqs.org/rfcs/rfc2617.html 0596 * @param string|false $user User name or false disable authentication 0597 * @param string $password Password 0598 * @param string $type Authentication type 0599 * @return Zend_Http_Client 0600 * @throws Zend_Http_Client_Exception 0601 */ 0602 public function setAuth($user, $password = '', $type = self::AUTH_BASIC) 0603 { 0604 // If we got false or null, disable authentication 0605 if ($user === false || $user === null) { 0606 $this->auth = null; 0607 0608 // Clear the auth information in the uri instance as well 0609 if ($this->uri instanceof Zend_Uri_Http) { 0610 $this->getUri()->setUsername(''); 0611 $this->getUri()->setPassword(''); 0612 } 0613 // Else, set up authentication 0614 } else { 0615 // Check we got a proper authentication type 0616 if (! defined('self::AUTH_' . strtoupper($type))) { 0617 /** @see Zend_Http_Client_Exception */ 0618 // require_once 'Zend/Http/Client/Exception.php'; 0619 throw new Zend_Http_Client_Exception("Invalid or not supported authentication type: '$type'"); 0620 } 0621 0622 $this->auth = array( 0623 'user' => (string) $user, 0624 'password' => (string) $password, 0625 'type' => $type 0626 ); 0627 } 0628 0629 return $this; 0630 } 0631 0632 /** 0633 * Set the HTTP client's cookie jar. 0634 * 0635 * A cookie jar is an object that holds and maintains cookies across HTTP requests 0636 * and responses. 0637 * 0638 * @param Zend_Http_CookieJar|boolean $cookiejar Existing cookiejar object, true to create a new one, false to disable 0639 * @return Zend_Http_Client 0640 * @throws Zend_Http_Client_Exception 0641 */ 0642 public function setCookieJar($cookiejar = true) 0643 { 0644 Zend_Loader::loadClass('Zend_Http_CookieJar'); 0645 0646 if ($cookiejar instanceof Zend_Http_CookieJar) { 0647 $this->cookiejar = $cookiejar; 0648 } elseif ($cookiejar === true) { 0649 $this->cookiejar = new Zend_Http_CookieJar(); 0650 } elseif (! $cookiejar) { 0651 $this->cookiejar = null; 0652 } else { 0653 /** @see Zend_Http_Client_Exception */ 0654 // require_once 'Zend/Http/Client/Exception.php'; 0655 throw new Zend_Http_Client_Exception('Invalid parameter type passed as CookieJar'); 0656 } 0657 0658 return $this; 0659 } 0660 0661 /** 0662 * Return the current cookie jar or null if none. 0663 * 0664 * @return Zend_Http_CookieJar|null 0665 */ 0666 public function getCookieJar() 0667 { 0668 return $this->cookiejar; 0669 } 0670 0671 /** 0672 * Add a cookie to the request. If the client has no Cookie Jar, the cookies 0673 * will be added directly to the headers array as "Cookie" headers. 0674 * 0675 * @param Zend_Http_Cookie|string $cookie 0676 * @param string|null $value If "cookie" is a string, this is the cookie value. 0677 * @return Zend_Http_Client 0678 * @throws Zend_Http_Client_Exception 0679 */ 0680 public function setCookie($cookie, $value = null) 0681 { 0682 Zend_Loader::loadClass('Zend_Http_Cookie'); 0683 0684 if (is_array($cookie)) { 0685 foreach ($cookie as $c => $v) { 0686 if (is_string($c)) { 0687 $this->setCookie($c, $v); 0688 } else { 0689 $this->setCookie($v); 0690 } 0691 } 0692 0693 return $this; 0694 } 0695 0696 if ($value !== null && $this->config['encodecookies']) { 0697 $value = urlencode($value); 0698 } 0699 0700 if (isset($this->cookiejar)) { 0701 if ($cookie instanceof Zend_Http_Cookie) { 0702 $this->cookiejar->addCookie($cookie); 0703 } elseif (is_string($cookie) && $value !== null) { 0704 $cookie = Zend_Http_Cookie::fromString("{$cookie}={$value}", 0705 $this->uri, 0706 $this->config['encodecookies']); 0707 $this->cookiejar->addCookie($cookie); 0708 } 0709 } else { 0710 if ($cookie instanceof Zend_Http_Cookie) { 0711 $name = $cookie->getName(); 0712 $value = $cookie->getValue(); 0713 $cookie = $name; 0714 } 0715 0716 if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) { 0717 /** @see Zend_Http_Client_Exception */ 0718 // require_once 'Zend/Http/Client/Exception.php'; 0719 throw new Zend_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})"); 0720 } 0721 0722 $value = addslashes($value); 0723 0724 if (! isset($this->headers['cookie'])) { 0725 $this->headers['cookie'] = array('Cookie', ''); 0726 } 0727 $this->headers['cookie'][1] .= $cookie . '=' . $value . '; '; 0728 } 0729 0730 return $this; 0731 } 0732 0733 /** 0734 * Set a file to upload (using a POST request) 0735 * 0736 * Can be used in two ways: 0737 * 0738 * 1. $data is null (default): $filename is treated as the name if a local file which 0739 * will be read and sent. Will try to guess the content type using mime_content_type(). 0740 * 2. $data is set - $filename is sent as the file name, but $data is sent as the file 0741 * contents and no file is read from the file system. In this case, you need to 0742 * manually set the Content-Type ($ctype) or it will default to 0743 * application/octet-stream. 0744 * 0745 * @param string $filename Name of file to upload, or name to save as 0746 * @param string $formname Name of form element to send as 0747 * @param string $data Data to send (if null, $filename is read and sent) 0748 * @param string $ctype Content type to use (if $data is set and $ctype is 0749 * null, will be application/octet-stream) 0750 * @return Zend_Http_Client 0751 * @throws Zend_Http_Client_Exception 0752 */ 0753 public function setFileUpload($filename, $formname, $data = null, $ctype = null) 0754 { 0755 if ($data === null) { 0756 if (($data = @file_get_contents($filename)) === false) { 0757 /** @see Zend_Http_Client_Exception */ 0758 // require_once 'Zend/Http/Client/Exception.php'; 0759 throw new Zend_Http_Client_Exception("Unable to read file '{$filename}' for upload"); 0760 } 0761 0762 if (! $ctype) { 0763 $ctype = $this->_detectFileMimeType($filename); 0764 } 0765 } 0766 0767 // Force enctype to multipart/form-data 0768 $this->setEncType(self::ENC_FORMDATA); 0769 0770 $this->files[] = array( 0771 'formname' => $formname, 0772 'filename' => basename($filename), 0773 'ctype' => $ctype, 0774 'data' => $data 0775 ); 0776 0777 $this->body_field_order[$formname] = self::VTYPE_FILE; 0778 0779 return $this; 0780 } 0781 0782 /** 0783 * Set the encoding type for POST data 0784 * 0785 * @param string $enctype 0786 * @return Zend_Http_Client 0787 */ 0788 public function setEncType($enctype = self::ENC_URLENCODED) 0789 { 0790 $this->enctype = $enctype; 0791 0792 return $this; 0793 } 0794 0795 /** 0796 * Set the raw (already encoded) POST data. 0797 * 0798 * This function is here for two reasons: 0799 * 1. For advanced user who would like to set their own data, already encoded 0800 * 2. For backwards compatibilty: If someone uses the old post($data) method. 0801 * this method will be used to set the encoded data. 0802 * 0803 * $data can also be stream (such as file) from which the data will be read. 0804 * 0805 * @param string|resource $data 0806 * @param string $enctype 0807 * @return Zend_Http_Client 0808 */ 0809 public function setRawData($data, $enctype = null) 0810 { 0811 $this->raw_post_data = $data; 0812 $this->setEncType($enctype); 0813 if (is_resource($data)) { 0814 // We've got stream data 0815 $stat = @fstat($data); 0816 if($stat) { 0817 $this->setHeaders(self::CONTENT_LENGTH, $stat['size']); 0818 } 0819 } 0820 return $this; 0821 } 0822 0823 /** 0824 * Set the unmask feature for GET parameters as array 0825 * 0826 * Example: 0827 * foo%5B0%5D=a&foo%5B1%5D=b 0828 * becomes 0829 * foo=a&foo=b 0830 * 0831 * This is usefull for some services 0832 * 0833 * @param boolean $status 0834 * @return Zend_Http_Client 0835 */ 0836 public function setUnmaskStatus($status = true) 0837 { 0838 $this->_unmaskStatus = (BOOL)$status; 0839 return $this; 0840 } 0841 0842 /** 0843 * Returns the currently configured unmask status 0844 * 0845 * @return boolean 0846 */ 0847 public function getUnmaskStatus() 0848 { 0849 return $this->_unmaskStatus; 0850 } 0851 0852 /** 0853 * Clear all GET and POST parameters 0854 * 0855 * Should be used to reset the request parameters if the client is 0856 * used for several concurrent requests. 0857 * 0858 * clearAll parameter controls if we clean just parameters or also 0859 * headers and last_* 0860 * 0861 * @param bool $clearAll Should all data be cleared? 0862 * @return Zend_Http_Client 0863 */ 0864 public function resetParameters($clearAll = false) 0865 { 0866 // Reset parameter data 0867 $this->paramsGet = array(); 0868 $this->paramsPost = array(); 0869 $this->files = array(); 0870 $this->raw_post_data = null; 0871 $this->enctype = null; 0872 0873 if($clearAll) { 0874 $this->headers = array(); 0875 $this->last_request = null; 0876 $this->last_response = null; 0877 } else { 0878 // Clear outdated headers 0879 if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) { 0880 unset($this->headers[strtolower(self::CONTENT_TYPE)]); 0881 } 0882 if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) { 0883 unset($this->headers[strtolower(self::CONTENT_LENGTH)]); 0884 } 0885 } 0886 0887 return $this; 0888 } 0889 0890 /** 0891 * Get the last HTTP request as string 0892 * 0893 * @return string 0894 */ 0895 public function getLastRequest() 0896 { 0897 return $this->last_request; 0898 } 0899 0900 /** 0901 * Get the last HTTP response received by this client 0902 * 0903 * If $config['storeresponse'] is set to false, or no response was 0904 * stored yet, will return null 0905 * 0906 * @return Zend_Http_Response or null if none 0907 */ 0908 public function getLastResponse() 0909 { 0910 return $this->last_response; 0911 } 0912 0913 /** 0914 * Load the connection adapter 0915 * 0916 * While this method is not called more than one for a client, it is 0917 * seperated from ->request() to preserve logic and readability 0918 * 0919 * @param Zend_Http_Client_Adapter_Interface|string $adapter 0920 * @return null 0921 * @throws Zend_Http_Client_Exception 0922 */ 0923 public function setAdapter($adapter) 0924 { 0925 if (is_string($adapter)) { 0926 try { 0927 Zend_Loader::loadClass($adapter); 0928 } catch (Zend_Exception $e) { 0929 /** @see Zend_Http_Client_Exception */ 0930 // require_once 'Zend/Http/Client/Exception.php'; 0931 throw new Zend_Http_Client_Exception("Unable to load adapter '$adapter': {$e->getMessage()}", 0, $e); 0932 } 0933 0934 $adapter = new $adapter; 0935 } 0936 0937 if (! $adapter instanceof Zend_Http_Client_Adapter_Interface) { 0938 /** @see Zend_Http_Client_Exception */ 0939 // require_once 'Zend/Http/Client/Exception.php'; 0940 throw new Zend_Http_Client_Exception('Passed adapter is not a HTTP connection adapter'); 0941 } 0942 0943 $this->adapter = $adapter; 0944 $config = $this->config; 0945 unset($config['adapter']); 0946 $this->adapter->setConfig($config); 0947 } 0948 0949 /** 0950 * Load the connection adapter 0951 * 0952 * @return Zend_Http_Client_Adapter_Interface $adapter 0953 */ 0954 public function getAdapter() 0955 { 0956 if (null === $this->adapter) { 0957 $this->setAdapter($this->config['adapter']); 0958 } 0959 0960 return $this->adapter; 0961 } 0962 0963 /** 0964 * Set streaming for received data 0965 * 0966 * @param string|boolean $streamfile Stream file, true for temp file, false/null for no streaming 0967 * @return Zend_Http_Client 0968 */ 0969 public function setStream($streamfile = true) 0970 { 0971 $this->setConfig(array("output_stream" => $streamfile)); 0972 return $this; 0973 } 0974 0975 /** 0976 * Get status of streaming for received data 0977 * @return boolean|string 0978 */ 0979 public function getStream() 0980 { 0981 return $this->config["output_stream"]; 0982 } 0983 0984 /** 0985 * Create temporary stream 0986 * 0987 * @return resource 0988 */ 0989 protected function _openTempStream() 0990 { 0991 $this->_stream_name = $this->config['output_stream']; 0992 if(!is_string($this->_stream_name)) { 0993 // If name is not given, create temp name 0994 $this->_stream_name = tempnam(isset($this->config['stream_tmp_dir'])?$this->config['stream_tmp_dir']:sys_get_temp_dir(), 0995 'Zend_Http_Client'); 0996 } 0997 0998 if (false === ($fp = @fopen($this->_stream_name, "w+b"))) { 0999 if ($this->adapter instanceof Zend_Http_Client_Adapter_Interface) { 1000 $this->adapter->close(); 1001 } 1002 // require_once 'Zend/Http/Client/Exception.php'; 1003 throw new Zend_Http_Client_Exception("Could not open temp file {$this->_stream_name}"); 1004 } 1005 1006 return $fp; 1007 } 1008 1009 /** 1010 * Send the HTTP request and return an HTTP response object 1011 * 1012 * @param string $method 1013 * @return Zend_Http_Response 1014 * @throws Zend_Http_Client_Exception 1015 */ 1016 public function request($method = null) 1017 { 1018 if (! $this->uri instanceof Zend_Uri_Http) { 1019 /** @see Zend_Http_Client_Exception */ 1020 // require_once 'Zend/Http/Client/Exception.php'; 1021 throw new Zend_Http_Client_Exception('No valid URI has been passed to the client'); 1022 } 1023 1024 if ($method) { 1025 $this->setMethod($method); 1026 } 1027 $this->redirectCounter = 0; 1028 $response = null; 1029 1030 // Make sure the adapter is loaded 1031 if ($this->adapter == null) { 1032 $this->setAdapter($this->config['adapter']); 1033 } 1034 1035 // Send the first request. If redirected, continue. 1036 do { 1037 // Clone the URI and add the additional GET parameters to it 1038 $uri = clone $this->uri; 1039 if (! empty($this->paramsGet)) { 1040 $query = $uri->getQuery(); 1041 if (! empty($query)) { 1042 $query .= '&'; 1043 } 1044 $query .= http_build_query($this->paramsGet, null, '&'); 1045 if ($this->config['rfc3986_strict']) { 1046 $query = str_replace('+', '%20', $query); 1047 } 1048 1049 // @see ZF-11671 to unmask for some services to foo=val1&foo=val2 1050 if ($this->getUnmaskStatus()) { 1051 if ($this->_queryBracketsEscaped) { 1052 $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $query); 1053 } else { 1054 $query = preg_replace('/\\[(?:[0-9]|[1-9][0-9]+)\\]=/', '=', $query); 1055 } 1056 } 1057 1058 $uri->setQuery($query); 1059 } 1060 1061 $body = $this->_prepareBody(); 1062 $headers = $this->_prepareHeaders(); 1063 1064 // check that adapter supports streaming before using it 1065 if(is_resource($body) && !($this->adapter instanceof Zend_Http_Client_Adapter_Stream)) { 1066 /** @see Zend_Http_Client_Exception */ 1067 // require_once 'Zend/Http/Client/Exception.php'; 1068 throw new Zend_Http_Client_Exception('Adapter does not support streaming'); 1069 } 1070 1071 // Open the connection, send the request and read the response 1072 $this->adapter->connect($uri->getHost(), $uri->getPort(), 1073 ($uri->getScheme() == 'https' ? true : false)); 1074 1075 if($this->config['output_stream']) { 1076 if($this->adapter instanceof Zend_Http_Client_Adapter_Stream) { 1077 $stream = $this->_openTempStream(); 1078 $this->adapter->setOutputStream($stream); 1079 } else { 1080 /** @see Zend_Http_Client_Exception */ 1081 // require_once 'Zend/Http/Client/Exception.php'; 1082 throw new Zend_Http_Client_Exception('Adapter does not support streaming'); 1083 } 1084 } 1085 1086 $this->last_request = $this->adapter->write($this->method, 1087 $uri, $this->config['httpversion'], $headers, $body); 1088 1089 $response = $this->adapter->read(); 1090 if (! $response) { 1091 /** @see Zend_Http_Client_Exception */ 1092 // require_once 'Zend/Http/Client/Exception.php'; 1093 throw new Zend_Http_Client_Exception('Unable to read response, or response is empty'); 1094 } 1095 1096 if($this->config['output_stream']) { 1097 $streamMetaData = stream_get_meta_data($stream); 1098 if ($streamMetaData['seekable']) { 1099 rewind($stream); 1100 } 1101 // cleanup the adapter 1102 $this->adapter->setOutputStream(null); 1103 $response = Zend_Http_Response_Stream::fromStream($response, $stream); 1104 $response->setStreamName($this->_stream_name); 1105 if(!is_string($this->config['output_stream'])) { 1106 // we used temp name, will need to clean up 1107 $response->setCleanup(true); 1108 } 1109 } else { 1110 $response = Zend_Http_Response::fromString($response); 1111 } 1112 1113 if ($this->config['storeresponse']) { 1114 $this->last_response = $response; 1115 } 1116 1117 // Load cookies into cookie jar 1118 if (isset($this->cookiejar)) { 1119 $this->cookiejar->addCookiesFromResponse($response, $uri, $this->config['encodecookies']); 1120 } 1121 1122 // If we got redirected, look for the Location header 1123 if ($response->isRedirect() && ($location = $response->getHeader('location'))) { 1124 1125 // Avoid problems with buggy servers that add whitespace at the 1126 // end of some headers (See ZF-11283) 1127 $location = trim($location); 1128 1129 // Check whether we send the exact same request again, or drop the parameters 1130 // and send a GET request 1131 if ($response->getStatus() == 303 || 1132 ((! $this->config['strictredirects']) && ($response->getStatus() == 302 || 1133 $response->getStatus() == 301))) { 1134 1135 $this->resetParameters(); 1136 $this->setMethod(self::GET); 1137 } 1138 1139 // If we got a well formed absolute URI 1140 if (($scheme = substr($location, 0, 6)) && ($scheme == 'http:/' || $scheme == 'https:')) { 1141 $this->setHeaders('host', null); 1142 $this->setUri($location); 1143 1144 } else { 1145 1146 // Split into path and query and set the query 1147 if (strpos($location, '?') !== false) { 1148 list($location, $query) = explode('?', $location, 2); 1149 } else { 1150 $query = ''; 1151 } 1152 $this->uri->setQuery($query); 1153 1154 // Else, if we got just an absolute path, set it 1155 if(strpos($location, '/') === 0) { 1156 $this->uri->setPath($location); 1157 1158 // Else, assume we have a relative path 1159 } else { 1160 // Get the current path directory, removing any trailing slashes 1161 $path = $this->uri->getPath(); 1162 $path = rtrim(substr($path, 0, strrpos($path, '/')), "/"); 1163 $this->uri->setPath($path . '/' . $location); 1164 } 1165 } 1166 ++$this->redirectCounter; 1167 1168 } else { 1169 // If we didn't get any location, stop redirecting 1170 break; 1171 } 1172 1173 } while ($this->redirectCounter < $this->config['maxredirects']); 1174 1175 return $response; 1176 } 1177 1178 /** 1179 * Prepare the request headers 1180 * 1181 * @return array 1182 */ 1183 protected function _prepareHeaders() 1184 { 1185 $headers = array(); 1186 1187 // Set the host header 1188 if (! isset($this->headers['host'])) { 1189 $host = $this->uri->getHost(); 1190 1191 // If the port is not default, add it 1192 if (! (($this->uri->getScheme() == 'http' && $this->uri->getPort() == 80) || 1193 ($this->uri->getScheme() == 'https' && $this->uri->getPort() == 443))) { 1194 $host .= ':' . $this->uri->getPort(); 1195 } 1196 1197 $headers[] = "Host: {$host}"; 1198 } 1199 1200 // Set the connection header 1201 if (! isset($this->headers['connection'])) { 1202 if (! $this->config['keepalive']) { 1203 $headers[] = "Connection: close"; 1204 } 1205 } 1206 1207 // Set the Accept-encoding header if not set - depending on whether 1208 // zlib is available or not. 1209 if (! isset($this->headers['accept-encoding'])) { 1210 if (function_exists('gzinflate')) { 1211 $headers[] = 'Accept-encoding: gzip, deflate'; 1212 } else { 1213 $headers[] = 'Accept-encoding: identity'; 1214 } 1215 } 1216 1217 // Set the Content-Type header 1218 if (($this->method == self::POST || $this->method == self::PUT) && 1219 (! isset($this->headers[strtolower(self::CONTENT_TYPE)]) && isset($this->enctype))) { 1220 1221 $headers[] = self::CONTENT_TYPE . ': ' . $this->enctype; 1222 } 1223 1224 // Set the user agent header 1225 if (! isset($this->headers['user-agent']) && isset($this->config['useragent'])) { 1226 $headers[] = "User-Agent: {$this->config['useragent']}"; 1227 } 1228 1229 // Set HTTP authentication if needed 1230 if (is_array($this->auth)) { 1231 $auth = self::encodeAuthHeader($this->auth['user'], $this->auth['password'], $this->auth['type']); 1232 $headers[] = "Authorization: {$auth}"; 1233 } 1234 1235 // Load cookies from cookie jar 1236 if (isset($this->cookiejar)) { 1237 $cookstr = $this->cookiejar->getMatchingCookies($this->uri, 1238 true, Zend_Http_CookieJar::COOKIE_STRING_CONCAT); 1239 1240 if ($cookstr) { 1241 $headers[] = "Cookie: {$cookstr}"; 1242 } 1243 } 1244 1245 // Add all other user defined headers 1246 foreach ($this->headers as $header) { 1247 list($name, $value) = $header; 1248 if (is_array($value)) { 1249 $value = implode(', ', $value); 1250 } 1251 1252 $headers[] = "$name: $value"; 1253 } 1254 1255 return $headers; 1256 } 1257 1258 /** 1259 * Prepare the request body (for POST and PUT requests) 1260 * 1261 * @return string 1262 * @throws Zend_Http_Client_Exception 1263 */ 1264 protected function _prepareBody() 1265 { 1266 // According to RFC2616, a TRACE request should not have a body. 1267 if ($this->method == self::TRACE) { 1268 return ''; 1269 } 1270 1271 if (isset($this->raw_post_data) && is_resource($this->raw_post_data)) { 1272 return $this->raw_post_data; 1273 } 1274 // If mbstring overloads substr and strlen functions, we have to 1275 // override it's internal encoding 1276 if (function_exists('mb_internal_encoding') && 1277 ((int) ini_get('mbstring.func_overload')) & 2) { 1278 1279 $mbIntEnc = mb_internal_encoding(); 1280 mb_internal_encoding('ASCII'); 1281 } 1282 1283 // If we have raw_post_data set, just use it as the body. 1284 if (isset($this->raw_post_data)) { 1285 $this->setHeaders(self::CONTENT_LENGTH, strlen($this->raw_post_data)); 1286 if (isset($mbIntEnc)) { 1287 mb_internal_encoding($mbIntEnc); 1288 } 1289 1290 return $this->raw_post_data; 1291 } 1292 1293 $body = ''; 1294 1295 // If we have files to upload, force enctype to multipart/form-data 1296 if (count ($this->files) > 0) { 1297 $this->setEncType(self::ENC_FORMDATA); 1298 } 1299 1300 // If we have POST parameters or files, encode and add them to the body 1301 if (count($this->paramsPost) > 0 || count($this->files) > 0) { 1302 switch($this->enctype) { 1303 case self::ENC_FORMDATA: 1304 // Encode body as multipart/form-data 1305 $boundary = '---ZENDHTTPCLIENT-' . md5(microtime()); 1306 $this->setHeaders(self::CONTENT_TYPE, self::ENC_FORMDATA . "; boundary={$boundary}"); 1307 1308 // Encode all files and POST vars in the order they were given 1309 foreach ($this->body_field_order as $fieldName=>$fieldType) { 1310 switch ($fieldType) { 1311 case self::VTYPE_FILE: 1312 foreach ($this->files as $file) { 1313 if ($file['formname']===$fieldName) { 1314 $fhead = array(self::CONTENT_TYPE => $file['ctype']); 1315 $body .= self::encodeFormData($boundary, $file['formname'], $file['data'], $file['filename'], $fhead); 1316 } 1317 } 1318 break; 1319 case self::VTYPE_SCALAR: 1320 if (isset($this->paramsPost[$fieldName])) { 1321 if (is_array($this->paramsPost[$fieldName])) { 1322 $flattened = self::_flattenParametersArray($this->paramsPost[$fieldName], $fieldName); 1323 foreach ($flattened as $pp) { 1324 $body .= self::encodeFormData($boundary, $pp[0], $pp[1]); 1325 } 1326 } else { 1327 $body .= self::encodeFormData($boundary, $fieldName, $this->paramsPost[$fieldName]); 1328 } 1329 } 1330 break; 1331 } 1332 } 1333 1334 $body .= "--{$boundary}--\r\n"; 1335 break; 1336 1337 case self::ENC_URLENCODED: 1338 // Encode body as application/x-www-form-urlencoded 1339 $this->setHeaders(self::CONTENT_TYPE, self::ENC_URLENCODED); 1340 $body = http_build_query($this->paramsPost, '', '&'); 1341 break; 1342 1343 default: 1344 if (isset($mbIntEnc)) { 1345 mb_internal_encoding($mbIntEnc); 1346 } 1347 1348 /** @see Zend_Http_Client_Exception */ 1349 // require_once 'Zend/Http/Client/Exception.php'; 1350 throw new Zend_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." . 1351 " Please use Zend_Http_Client::setRawData to send this kind of content."); 1352 break; 1353 } 1354 } 1355 1356 // Set the Content-Length if we have a body or if request is POST/PUT 1357 if ($body || $this->method == self::POST || $this->method == self::PUT) { 1358 $this->setHeaders(self::CONTENT_LENGTH, strlen($body)); 1359 } 1360 1361 if (isset($mbIntEnc)) { 1362 mb_internal_encoding($mbIntEnc); 1363 } 1364 1365 return $body; 1366 } 1367 1368 /** 1369 * Helper method that gets a possibly multi-level parameters array (get or 1370 * post) and flattens it. 1371 * 1372 * The method returns an array of (key, value) pairs (because keys are not 1373 * necessarily unique. If one of the parameters in as array, it will also 1374 * add a [] suffix to the key. 1375 * 1376 * This method is deprecated since Zend Framework 1.9 in favour of 1377 * self::_flattenParametersArray() and will be dropped in 2.0 1378 * 1379 * @deprecated since 1.9 1380 * 1381 * @param array $parray The parameters array 1382 * @param bool $urlencode Whether to urlencode the name and value 1383 * @return array 1384 */ 1385 protected function _getParametersRecursive($parray, $urlencode = false) 1386 { 1387 // Issue a deprecated notice 1388 trigger_error("The " . __METHOD__ . " method is deprecated and will be dropped in 2.0.", 1389 E_USER_NOTICE); 1390 1391 if (! is_array($parray)) { 1392 return $parray; 1393 } 1394 $parameters = array(); 1395 1396 foreach ($parray as $name => $value) { 1397 if ($urlencode) { 1398 $name = urlencode($name); 1399 } 1400 1401 // If $value is an array, iterate over it 1402 if (is_array($value)) { 1403 $name .= ($urlencode ? '%5B%5D' : '[]'); 1404 foreach ($value as $subval) { 1405 if ($urlencode) { 1406 $subval = urlencode($subval); 1407 } 1408 $parameters[] = array($name, $subval); 1409 } 1410 } else { 1411 if ($urlencode) { 1412 $value = urlencode($value); 1413 } 1414 $parameters[] = array($name, $value); 1415 } 1416 } 1417 1418 return $parameters; 1419 } 1420 1421 /** 1422 * Attempt to detect the MIME type of a file using available extensions 1423 * 1424 * This method will try to detect the MIME type of a file. If the fileinfo 1425 * extension is available, it will be used. If not, the mime_magic 1426 * extension which is deprected but is still available in many PHP setups 1427 * will be tried. 1428 * 1429 * If neither extension is available, the default application/octet-stream 1430 * MIME type will be returned 1431 * 1432 * @param string $file File path 1433 * @return string MIME type 1434 */ 1435 protected function _detectFileMimeType($file) 1436 { 1437 $type = null; 1438 1439 // First try with fileinfo functions 1440 if (function_exists('finfo_open')) { 1441 if (self::$_fileInfoDb === null) { 1442 self::$_fileInfoDb = @finfo_open(FILEINFO_MIME); 1443 } 1444 1445 if (self::$_fileInfoDb) { 1446 $type = finfo_file(self::$_fileInfoDb, $file); 1447 } 1448 1449 } elseif (function_exists('mime_content_type')) { 1450 $type = mime_content_type($file); 1451 } 1452 1453 // Fallback to the default application/octet-stream 1454 if (! $type) { 1455 $type = 'application/octet-stream'; 1456 } 1457 1458 return $type; 1459 } 1460 1461 /** 1462 * Encode data to a multipart/form-data part suitable for a POST request. 1463 * 1464 * @param string $boundary 1465 * @param string $name 1466 * @param mixed $value 1467 * @param string $filename 1468 * @param array $headers Associative array of optional headers @example ("Content-Transfer-Encoding" => "binary") 1469 * @return string 1470 */ 1471 public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) 1472 { 1473 $ret = "--{$boundary}\r\n" . 1474 'Content-Disposition: form-data; name="' . $name .'"'; 1475 1476 if ($filename) { 1477 $ret .= '; filename="' . $filename . '"'; 1478 } 1479 $ret .= "\r\n"; 1480 1481 foreach ($headers as $hname => $hvalue) { 1482 $ret .= "{$hname}: {$hvalue}\r\n"; 1483 } 1484 $ret .= "\r\n"; 1485 1486 $ret .= "{$value}\r\n"; 1487 1488 return $ret; 1489 } 1490 1491 /** 1492 * Create a HTTP authentication "Authorization:" header according to the 1493 * specified user, password and authentication method. 1494 * 1495 * @see http://www.faqs.org/rfcs/rfc2617.html 1496 * @param string $user 1497 * @param string $password 1498 * @param string $type 1499 * @return string 1500 * @throws Zend_Http_Client_Exception 1501 */ 1502 public static function encodeAuthHeader($user, $password, $type = self::AUTH_BASIC) 1503 { 1504 $authHeader = null; 1505 1506 switch ($type) { 1507 case self::AUTH_BASIC: 1508 // In basic authentication, the user name cannot contain ":" 1509 if (strpos($user, ':') !== false) { 1510 /** @see Zend_Http_Client_Exception */ 1511 // require_once 'Zend/Http/Client/Exception.php'; 1512 throw new Zend_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication"); 1513 } 1514 1515 $authHeader = 'Basic ' . base64_encode($user . ':' . $password); 1516 break; 1517 1518 //case self::AUTH_DIGEST: 1519 /** 1520 * @todo Implement digest authentication 1521 */ 1522 // break; 1523 1524 default: 1525 /** @see Zend_Http_Client_Exception */ 1526 // require_once 'Zend/Http/Client/Exception.php'; 1527 throw new Zend_Http_Client_Exception("Not a supported HTTP authentication type: '$type'"); 1528 } 1529 1530 return $authHeader; 1531 } 1532 1533 /** 1534 * Convert an array of parameters into a flat array of (key, value) pairs 1535 * 1536 * Will flatten a potentially multi-dimentional array of parameters (such 1537 * as POST parameters) into a flat array of (key, value) paris. In case 1538 * of multi-dimentional arrays, square brackets ([]) will be added to the 1539 * key to indicate an array. 1540 * 1541 * @since 1.9 1542 * 1543 * @param array $parray 1544 * @param string $prefix 1545 * @return array 1546 */ 1547 protected static function _flattenParametersArray($parray, $prefix = null) 1548 { 1549 if (! is_array($parray)) { 1550 return $parray; 1551 } 1552 1553 $parameters = array(); 1554 1555 foreach($parray as $name => $value) { 1556 1557 // Calculate array key 1558 if ($prefix) { 1559 if (is_int($name)) { 1560 $key = $prefix . '[]'; 1561 } else { 1562 $key = $prefix . "[$name]"; 1563 } 1564 } else { 1565 $key = $name; 1566 } 1567 1568 if (is_array($value)) { 1569 $parameters = array_merge($parameters, self::_flattenParametersArray($value, $key)); 1570 1571 } else { 1572 $parameters[] = array($key, $value); 1573 } 1574 } 1575 1576 return $parameters; 1577 } 1578 1579 /** 1580 * Ensure a header value is valid per RFC 7230. 1581 * 1582 * @see http://tools.ietf.org/html/rfc7230#section-3.2 1583 * @param string|object|array $value 1584 * @param bool $recurse 1585 */ 1586 protected function _validateHeaderValue($value, $recurse = true) 1587 { 1588 if (is_array($value) && $recurse) { 1589 foreach ($value as $v) { 1590 $this->_validateHeaderValue($v, false); 1591 } 1592 return; 1593 } 1594 1595 // Cast integers and floats to strings for purposes of header representation. 1596 if (is_int($value) || is_float($value)) { 1597 $value = (string) $value; 1598 } 1599 1600 if (! is_string($value) && (! is_object($value) || ! method_exists($value, '__toString'))) { 1601 // require_once 'Zend/Http/Exception.php'; 1602 throw new Zend_Http_Exception('Invalid header value detected'); 1603 } 1604 1605 Zend_Http_Header_HeaderValue::assertValid($value); 1606 } 1607 }