Microsoft_Http
[ class tree: Microsoft_Http ] [ index: Microsoft_Http ] [ all elements ]

Source for file Client.php

Documentation is available at Client.php

  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 license@zend.com so we can send you a copy immediately.
  15.  *
  16.  * @category   Microsoft
  17.  * @package    Microsoft_Http
  18.  * @subpackage Client
  19.  * @version    $Id: Client.php 19661 2009-12-15 18:03:07Z matthew $
  20.  * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  21.  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  22.  */
  23.  
  24.  
  25. /**
  26.  * @see Microsoft_AutoLoader
  27.  */
  28. require_once dirname(__FILE__'/../AutoLoader.php';
  29.  
  30. /**
  31.  * Microsoft_Http_Client is an implemetation of an HTTP client in PHP. The client
  32.  * supports basic features like sending different HTTP requests and handling
  33.  * redirections, as well as more advanced features like proxy settings, HTTP
  34.  * authentication and cookie persistance (using a Microsoft_Http_CookieJar object)
  35.  *
  36.  * @todo Implement proxy settings
  37.  * @category   Microsoft
  38.  * @package    Microsoft_Http
  39.  * @subpackage Client
  40.  * @throws     Microsoft_Http_Client_Exception
  41.  * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  42.  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  43.  */
  44. {
  45.     /**
  46.      * HTTP request methods
  47.      */
  48.     const GET     'GET';
  49.     const POST    'POST';
  50.     const PUT     'PUT';
  51.     const HEAD    'HEAD';
  52.     const DELETE  'DELETE';
  53.     const TRACE   'TRACE';
  54.     const OPTIONS 'OPTIONS';
  55.     const CONNECT 'CONNECT';
  56.     const MERGE   'MERGE';
  57.  
  58.     /**
  59.      * Supported HTTP Authentication methods
  60.      */
  61.     const AUTH_BASIC 'basic';
  62.     //const AUTH_DIGEST = 'digest'; <-- not implemented yet
  63.  
  64.     /**
  65.      * HTTP protocol versions
  66.      */
  67.     const HTTP_1 '1.1';
  68.     const HTTP_0 '1.0';
  69.  
  70.     /**
  71.      * Content attributes
  72.      */
  73.     const CONTENT_TYPE   'Content-Type';
  74.     const CONTENT_LENGTH 'Content-Length';
  75.  
  76.     /**
  77.      * POST data encoding methods
  78.      */
  79.     const ENC_URLENCODED 'application/x-www-form-urlencoded';
  80.     const ENC_FORMDATA   'multipart/form-data';
  81.  
  82.     /**
  83.      * Configuration array, set using the constructor or using ::setConfig()
  84.      *
  85.      * @var array 
  86.      */
  87.     protected $config = array(
  88.         'maxredirects'    => 5,
  89.         'strictredirects' => false,
  90.         'useragent'       => 'Microsoft_Http_Client',
  91.         'timeout'         => 10,
  92.         'adapter'         => 'Microsoft_Http_Client_Adapter_Socket',
  93.         'httpversion'     => self::HTTP_1,
  94.         'keepalive'       => false,
  95.         'storeresponse'   => true,
  96.         'strict'          => true,
  97.         'output_stream'      => false,
  98.     );
  99.  
  100.     /**
  101.      * The adapter used to preform the actual connection to the server
  102.      *
  103.      * @var Microsoft_Http_Client_Adapter_Interface 
  104.      */
  105.     protected $adapter = null;
  106.  
  107.     /**
  108.      * Request URI
  109.      *
  110.      * @var Microsoft_Uri_Http 
  111.      */
  112.     protected $uri = null;
  113.  
  114.     /**
  115.      * Associative array of request headers
  116.      *
  117.      * @var array 
  118.      */
  119.     protected $headers = array();
  120.  
  121.     /**
  122.      * HTTP request method
  123.      *
  124.      * @var string 
  125.      */
  126.     protected $method = self::GET;
  127.  
  128.     /**
  129.      * Associative array of GET parameters
  130.      *
  131.      * @var array 
  132.      */
  133.     protected $paramsGet = array();
  134.  
  135.     /**
  136.      * Assiciative array of POST parameters
  137.      *
  138.      * @var array 
  139.      */
  140.     protected $paramsPost = array();
  141.  
  142.     /**
  143.      * Request body content type (for POST requests)
  144.      *
  145.      * @var string 
  146.      */
  147.     protected $enctype = null;
  148.  
  149.     /**
  150.      * The raw post data to send. Could be set by setRawData($data, $enctype).
  151.      *
  152.      * @var string 
  153.      */
  154.     protected $raw_post_data = null;
  155.  
  156.     /**
  157.      * HTTP Authentication settings
  158.      *
  159.      * Expected to be an associative array with this structure:
  160.      * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic')
  161.      * Where 'type' should be one of the supported authentication types (see the AUTH_*
  162.      * constants), for example 'basic' or 'digest'.
  163.      *
  164.      * If null, no authentication will be used.
  165.      *
  166.      * @var array|null
  167.      */
  168.     protected $auth;
  169.  
  170.     /**
  171.      * File upload arrays (used in POST requests)
  172.      *
  173.      * An associative array, where each element is of the format:
  174.      *   'name' => array('filename.txt', 'text/plain', 'This is the actual file contents')
  175.      *
  176.      * @var array 
  177.      */
  178.     protected $files = array();
  179.  
  180.     /**
  181.      * The client's cookie jar
  182.      *
  183.      * @var Microsoft_Http_CookieJar 
  184.      */
  185.     protected $cookiejar = null;
  186.  
  187.     /**
  188.      * The last HTTP request sent by the client, as string
  189.      *
  190.      * @var string 
  191.      */
  192.     protected $last_request = null;
  193.  
  194.     /**
  195.      * The last HTTP response received by the client
  196.      *
  197.      * @var Microsoft_Http_Response 
  198.      */
  199.     protected $last_response = null;
  200.  
  201.     /**
  202.      * Redirection counter
  203.      *
  204.      * @var int 
  205.      */
  206.     protected $redirectCounter = 0;
  207.  
  208.     /**
  209.      * Fileinfo magic database resource
  210.      *
  211.      * This varaiable is populated the first time _detectFileMimeType is called
  212.      * and is then reused on every call to this method
  213.      *
  214.      * @var resource 
  215.      */
  216.     static protected $_fileInfoDb = null;
  217.  
  218.     /**
  219.      * Contructor method. Will create a new HTTP client. Accepts the target
  220.      * URL and optionally configuration array.
  221.      *
  222.      * @param Microsoft_Uri_Http|string$uri 
  223.      * @param array $config Configuration key-value pairs.
  224.      */
  225.     public function __construct($uri null$config null)
  226.     {
  227.         if ($uri !== null{
  228.             $this->setUri($uri);
  229.         }
  230.         if ($config !== null{
  231.             $this->setConfig($config);
  232.         }
  233.     }
  234.  
  235.     /**
  236.      * Set the URI for the next request
  237.      *
  238.      * @param  Microsoft_Uri_Http|string$uri 
  239.      * @return Microsoft_Http_Client 
  240.      * @throws Microsoft_Http_Client_Exception
  241.      */
  242.     public function setUri($uri)
  243.     {
  244.         if (is_string($uri)) {
  245.             $uri Microsoft_Uri::factory($uri);
  246.         }
  247.  
  248.         if (!$uri instanceof Microsoft_Uri_Http{
  249.             /** @see Microsoft_Http_Client_Exception */
  250.             require_once 'Microsoft/Http/Client/Exception.php';
  251.             throw new Microsoft_Http_Client_Exception('Passed parameter is not a valid HTTP URI.');
  252.         }
  253.  
  254.         // Set auth if username and password has been specified in the uri
  255.         if ($uri->getUsername(&& $uri->getPassword()) {
  256.             $this->setAuth($uri->getUsername()$uri->getPassword());
  257.         }
  258.  
  259.         // We have no ports, set the defaults
  260.         if ($uri->getPort()) {
  261.             $uri->setPort(($uri->getScheme(== 'https' 443 80));
  262.         }
  263.  
  264.         $this->uri = $uri;
  265.  
  266.         return $this;
  267.     }
  268.  
  269.     /**
  270.      * Get the URI for the next request
  271.      *
  272.      * @param boolean $as_string If true, will return the URI as a string
  273.      * @return Microsoft_Uri_Http|string
  274.      */
  275.     public function getUri($as_string false)
  276.     {
  277.         if ($as_string && $this->uri instanceof Microsoft_Uri_Http{
  278.             return $this->uri->__toString();
  279.         else {
  280.             return $this->uri;
  281.         }
  282.     }
  283.  
  284.     /**
  285.      * Set configuration parameters for this HTTP client
  286.      *
  287.      * @param  Microsoft_Config | array $config
  288.      * @return Microsoft_Http_Client 
  289.      * @throws Microsoft_Http_Client_Exception
  290.      */
  291.     public function setConfig($config array())
  292.     {
  293.         if ($config instanceof Microsoft_Config{
  294.             $config $config->toArray();
  295.  
  296.         elseif (is_array($config)) {
  297.             /** @see Microsoft_Http_Client_Exception */
  298.             require_once 'Microsoft/Http/Client/Exception.php';
  299.             throw new Microsoft_Http_Client_Exception('Array expected, got ' gettype($config));
  300.         }
  301.  
  302.         foreach ($config as $k => $v{
  303.             $this->config[strtolower($k)$v;
  304.         }
  305.  
  306.         // Pass configuration options to the adapter if it exists
  307.         if ($this->adapter instanceof Microsoft_Http_Client_Adapter_Interface{
  308.             $this->adapter->setConfig($config);
  309.         }
  310.  
  311.         return $this;
  312.     }
  313.  
  314.     /**
  315.      * Set the next request's method
  316.      *
  317.      * Validated the passed method and sets it. If we have files set for
  318.      * POST requests, and the new method is not POST, the files are silently
  319.      * dropped.
  320.      *
  321.      * @param string $method 
  322.      * @return Microsoft_Http_Client 
  323.      * @throws Microsoft_Http_Client_Exception
  324.      */
  325.     public function setMethod($method self::GET)
  326.     {
  327.         if (preg_match('/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/'$method)) {
  328.             /** @see Microsoft_Http_Client_Exception */
  329.             require_once 'Microsoft/Http/Client/Exception.php';
  330.             throw new Microsoft_Http_Client_Exception("'{$method}' is not a valid HTTP request method.");
  331.         }
  332.  
  333.         if ($method == self::POST && $this->enctype === null{
  334.             $this->setEncType(self::ENC_URLENCODED);
  335.         }
  336.  
  337.         $this->method = $method;
  338.  
  339.         return $this;
  340.     }
  341.  
  342.     /**
  343.      * Set one or more request headers
  344.      *
  345.      * This function can be used in several ways to set the client's request
  346.      * headers:
  347.      * 1. By providing two parameters: $name as the header to set (eg. 'Host')
  348.      *    and $value as it's value (eg. 'www.example.com').
  349.      * 2. By providing a single header string as the only parameter
  350.      *    eg. 'Host: www.example.com'
  351.      * 3. By providing an array of headers as the first parameter
  352.      *    eg. array('host' => 'www.example.com', 'x-foo: bar'). In This case
  353.      *    the function will call itself recursively for each array item.
  354.      *
  355.      * @param string|array$name Header name, full header string ('Header: value')
  356.      *      or an array of headers
  357.      * @param mixed $value Header value or null
  358.      * @return Microsoft_Http_Client 
  359.      * @throws Microsoft_Http_Client_Exception
  360.      */
  361.     public function setHeaders($name$value null)
  362.     {
  363.         // If we got an array, go recusive!
  364.         if (is_array($name)) {
  365.             foreach ($name as $k => $v{
  366.                 if (is_string($k)) {
  367.                     $this->setHeaders($k$v);
  368.                 else {
  369.                     $this->setHeaders($vnull);
  370.                 }
  371.             }
  372.         else {
  373.             // Check if $name needs to be split
  374.             if ($value === null && (strpos($name':'0)) {
  375.                 list($name$valueexplode(':'$name2);
  376.             }
  377.  
  378.             // Make sure the name is valid if we are in strict mode
  379.             if ($this->config['strict'&& (preg_match('/^[a-zA-Z0-9-]+$/'$name))) {
  380.                 /** @see Microsoft_Http_Client_Exception */
  381.                 require_once 'Microsoft/Http/Client/Exception.php';
  382.                 throw new Microsoft_Http_Client_Exception("{$name} is not a valid HTTP header name");
  383.             }
  384.  
  385.             $normalized_name strtolower($name);
  386.  
  387.             // If $value is null or false, unset the header
  388.             if ($value === null || $value === false{
  389.                 unset($this->headers[$normalized_name]);
  390.  
  391.             // Else, set the header
  392.             else {
  393.                 // Header names are stored lowercase internally.
  394.                 if (is_string($value)) {
  395.                     $value trim($value);
  396.                 }
  397.                 $this->headers[$normalized_namearray($name$value);
  398.             }
  399.         }
  400.  
  401.         return $this;
  402.     }
  403.  
  404.     /**
  405.      * Get the value of a specific header
  406.      *
  407.      * Note that if the header has more than one value, an array
  408.      * will be returned.
  409.      *
  410.      * @param string $key 
  411.      * @return string|array|nullThe header value or null if it is not set
  412.      */
  413.     public function getHeader($key)
  414.     {
  415.         $key strtolower($key);
  416.         if (isset($this->headers[$key])) {
  417.             return $this->headers[$key][1];
  418.         else {
  419.             return null;
  420.         }
  421.     }
  422.  
  423.     /**
  424.      * Set a GET parameter for the request. Wrapper around _setParameter
  425.      *
  426.      * @param string|array$name 
  427.      * @param string $value 
  428.      * @return Microsoft_Http_Client 
  429.      */
  430.     public function setParameterGet($name$value null)
  431.     {
  432.         if (is_array($name)) {
  433.             foreach ($name as $k => $v)
  434.                 $this->_setParameter('GET'$k$v);
  435.         else {
  436.             $this->_setParameter('GET'$name$value);
  437.         }
  438.  
  439.         return $this;
  440.     }
  441.  
  442.     /**
  443.      * Set a POST parameter for the request. Wrapper around _setParameter
  444.      *
  445.      * @param string|array$name 
  446.      * @param string $value 
  447.      * @return Microsoft_Http_Client 
  448.      */
  449.     public function setParameterPost($name$value null)
  450.     {
  451.         if (is_array($name)) {
  452.             foreach ($name as $k => $v)
  453.                 $this->_setParameter('POST'$k$v);
  454.         else {
  455.             $this->_setParameter('POST'$name$value);
  456.         }
  457.  
  458.         return $this;
  459.     }
  460.  
  461.     /**
  462.      * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost
  463.      *
  464.      * @param string $type GET or POST
  465.      * @param string $name 
  466.      * @param string $value 
  467.      * @return null 
  468.      */
  469.     protected function _setParameter($type$name$value)
  470.     {
  471.         $parray array();
  472.         $type strtolower($type);
  473.         switch ($type{
  474.             case 'get':
  475.                 $parray &$this->paramsGet;
  476.                 break;
  477.             case 'post':
  478.                 $parray &$this->paramsPost;
  479.                 break;
  480.         }
  481.  
  482.         if ($value === null{
  483.             if (isset($parray[$name])) unset($parray[$name]);
  484.         else {
  485.             $parray[$name$value;
  486.         }
  487.     }
  488.  
  489.     /**
  490.      * Get the number of redirections done on the last request
  491.      *
  492.      * @return int 
  493.      */
  494.     public function getRedirectionsCount()
  495.     {
  496.         return $this->redirectCounter;
  497.     }
  498.  
  499.     /**
  500.      * Set HTTP authentication parameters
  501.      *
  502.      * $type should be one of the supported types - see the self::AUTH_*
  503.      * constants.
  504.      *
  505.      * To enable authentication:
  506.      * <code>
  507.      * $this->setAuth('shahar', 'secret', Microsoft_Http_Client::AUTH_BASIC);
  508.      * </code>
  509.      *
  510.      * To disable authentication:
  511.      * <code>
  512.      * $this->setAuth(false);
  513.      * </code>
  514.      *
  515.      * @see http://www.faqs.org/rfcs/rfc2617.html
  516.      * @param string|false$user User name or false disable authentication
  517.      * @param string $password Password
  518.      * @param string $type Authentication type
  519.      * @return Microsoft_Http_Client 
  520.      * @throws Microsoft_Http_Client_Exception
  521.      */
  522.     public function setAuth($user$password ''$type self::AUTH_BASIC)
  523.     {
  524.         // If we got false or null, disable authentication
  525.         if ($user === false || $user === null{
  526.             $this->auth = null;
  527.  
  528.             // Clear the auth information in the uri instance as well
  529.             if ($this->uri instanceof Microsoft_Uri_Http{
  530.                 $this->getUri()->setUsername('');
  531.                 $this->getUri()->setPassword('');
  532.             }
  533.         // Else, set up authentication
  534.         else {
  535.             // Check we got a proper authentication type
  536.             if (defined('self::AUTH_' strtoupper($type))) {
  537.                 /** @see Microsoft_Http_Client_Exception */
  538.                 require_once 'Microsoft/Http/Client/Exception.php';
  539.                 throw new Microsoft_Http_Client_Exception("Invalid or not supported authentication type: '$type'");
  540.             }
  541.  
  542.             $this->auth = array(
  543.                 'user' => (string) $user,
  544.                 'password' => (string) $password,
  545.                 'type' => $type
  546.             );
  547.         }
  548.  
  549.         return $this;
  550.     }
  551.  
  552.     /**
  553.      * Set the HTTP client's cookie jar.
  554.      *
  555.      * A cookie jar is an object that holds and maintains cookies across HTTP requests
  556.      * and responses.
  557.      *
  558.      * @param Microsoft_Http_CookieJar|boolean$cookiejar Existing cookiejar object, true to create a new one, false to disable
  559.      * @return Microsoft_Http_Client 
  560.      * @throws Microsoft_Http_Client_Exception
  561.      */
  562.     public function setCookieJar($cookiejar true)
  563.     {
  564.         if (class_exists('Microsoft_Http_CookieJar')) {
  565.             require_once 'Microsoft/Http/CookieJar.php';
  566.         }
  567.  
  568.         if ($cookiejar instanceof Microsoft_Http_CookieJar{
  569.             $this->cookiejar = $cookiejar;
  570.         elseif ($cookiejar === true{
  571.             $this->cookiejar = new Microsoft_Http_CookieJar();
  572.         elseif ($cookiejar{
  573.             $this->cookiejar = null;
  574.         else {
  575.             /** @see Microsoft_Http_Client_Exception */
  576.             require_once 'Microsoft/Http/Client/Exception.php';
  577.             throw new Microsoft_Http_Client_Exception('Invalid parameter type passed as CookieJar');
  578.         }
  579.  
  580.         return $this;
  581.     }
  582.  
  583.     /**
  584.      * Return the current cookie jar or null if none.
  585.      *
  586.      * @return Microsoft_Http_CookieJar|null
  587.      */
  588.     public function getCookieJar()
  589.     {
  590.         return $this->cookiejar;
  591.     }
  592.  
  593.     /**
  594.      * Add a cookie to the request. If the client has no Cookie Jar, the cookies
  595.      * will be added directly to the headers array as "Cookie" headers.
  596.      *
  597.      * @param Microsoft_Http_Cookie|string$cookie 
  598.      * @param string|null$value If "cookie" is a string, this is the cookie value.
  599.      * @return Microsoft_Http_Client 
  600.      * @throws Microsoft_Http_Client_Exception
  601.      */
  602.     public function setCookie($cookie$value null)
  603.     {
  604.         if (class_exists('Microsoft_Http_Cookie')) {
  605.             require_once 'Microsoft/Http/Cookie.php';
  606.         }
  607.  
  608.         if (is_array($cookie)) {
  609.             foreach ($cookie as $c => $v{
  610.                 if (is_string($c)) {
  611.                     $this->setCookie($c$v);
  612.                 else {
  613.                     $this->setCookie($v);
  614.                 }
  615.             }
  616.  
  617.             return $this;
  618.         }
  619.  
  620.         if ($value !== null{
  621.             $value urlencode($value);
  622.         }
  623.  
  624.         if (isset($this->cookiejar)) {
  625.             if ($cookie instanceof Microsoft_Http_Cookie{
  626.                 $this->cookiejar->addCookie($cookie);
  627.             elseif (is_string($cookie&& $value !== null{
  628.                 $cookie Microsoft_Http_Cookie::fromString("{$cookie}={$value}"$this->uri);
  629.                 $this->cookiejar->addCookie($cookie);
  630.             }
  631.         else {
  632.             if ($cookie instanceof Microsoft_Http_Cookie{
  633.                 $name $cookie->getName();
  634.                 $value $cookie->getValue();
  635.                 $cookie $name;
  636.             }
  637.  
  638.             if (preg_match("/[=,; \t\r\n\013\014]/"$cookie)) {
  639.                 /** @see Microsoft_Http_Client_Exception */
  640.                 require_once 'Microsoft/Http/Client/Exception.php';
  641.                 throw new Microsoft_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})");
  642.             }
  643.  
  644.             $value addslashes($value);
  645.  
  646.             if (isset($this->headers['cookie'])) {
  647.                 $this->headers['cookie'array('Cookie''');
  648.             }
  649.             $this->headers['cookie'][1.= $cookie '=' $value '; ';
  650.         }
  651.  
  652.         return $this;
  653.     }
  654.  
  655.     /**
  656.      * Set a file to upload (using a POST request)
  657.      *
  658.      * Can be used in two ways:
  659.      *
  660.      * 1. $data is null (default): $filename is treated as the name if a local file which
  661.      *    will be read and sent. Will try to guess the content type using mime_content_type().
  662.      * 2. $data is set - $filename is sent as the file name, but $data is sent as the file
  663.      *    contents and no file is read from the file system. In this case, you need to
  664.      *    manually set the Content-Type ($ctype) or it will default to
  665.      *    application/octet-stream.
  666.      *
  667.      * @param string $filename Name of file to upload, or name to save as
  668.      * @param string $formname Name of form element to send as
  669.      * @param string $data Data to send (if null, $filename is read and sent)
  670.      * @param string $ctype Content type to use (if $data is set and $ctype is
  671.      *      null, will be application/octet-stream)
  672.      * @return Microsoft_Http_Client 
  673.      * @throws Microsoft_Http_Client_Exception
  674.      */
  675.     public function setFileUpload($filename$formname$data null$ctype null)
  676.     {
  677.         if ($data === null{
  678.             if (($data @file_get_contents($filename)) === false{
  679.                 /** @see Microsoft_Http_Client_Exception */
  680.                 require_once 'Microsoft/Http/Client/Exception.php';
  681.                 throw new Microsoft_Http_Client_Exception("Unable to read file '{$filename}' for upload");
  682.             }
  683.  
  684.             if ($ctype{
  685.                 $ctype $this->_detectFileMimeType($filename);
  686.             }
  687.         }
  688.  
  689.         // Force enctype to multipart/form-data
  690.         $this->setEncType(self::ENC_FORMDATA);
  691.  
  692.         $this->files[array(
  693.             'formname' => $formname,
  694.             'filename' => basename($filename),
  695.             'ctype'    => $ctype,
  696.             'data'     => $data
  697.         );
  698.  
  699.         return $this;
  700.     }
  701.  
  702.     /**
  703.      * Set the encoding type for POST data
  704.      *
  705.      * @param string $enctype 
  706.      * @return Microsoft_Http_Client 
  707.      */
  708.     public function setEncType($enctype self::ENC_URLENCODED)
  709.     {
  710.         $this->enctype = $enctype;
  711.  
  712.         return $this;
  713.     }
  714.  
  715.     /**
  716.      * Set the raw (already encoded) POST data.
  717.      *
  718.      * This function is here for two reasons:
  719.      * 1. For advanced user who would like to set their own data, already encoded
  720.      * 2. For backwards compatibilty: If someone uses the old post($data) method.
  721.      *    this method will be used to set the encoded data.
  722.      *
  723.      * $data can also be stream (such as file) from which the data will be read.
  724.      *
  725.      * @param string|resource$data 
  726.      * @param string $enctype 
  727.      * @return Microsoft_Http_Client 
  728.      */
  729.     public function setRawData($data$enctype null)
  730.     {
  731.         $this->raw_post_data = $data;
  732.         $this->setEncType($enctype);
  733.         if (is_resource($data)) {
  734.             // We've got stream data
  735.             $stat @fstat($data);
  736.             if($stat{
  737.                 $this->setHeaders(self::CONTENT_LENGTH$stat['size']);
  738.             }
  739.         }
  740.         return $this;
  741.     }
  742.  
  743.     /**
  744.      * Clear all GET and POST parameters
  745.      *
  746.      * Should be used to reset the request parameters if the client is
  747.      * used for several concurrent requests.
  748.      *
  749.      * clearAll parameter controls if we clean just parameters or also
  750.      * headers and last_*
  751.      *
  752.      * @param bool $clearAll Should all data be cleared?
  753.      * @return Microsoft_Http_Client 
  754.      */
  755.     public function resetParameters($clearAll false)
  756.     {
  757.         // Reset parameter data
  758.         $this->paramsGet     = array();
  759.         $this->paramsPost    = array();
  760.         $this->files         = array();
  761.         $this->raw_post_data = null;
  762.  
  763.         if($clearAll{
  764.             $this->headers = array();
  765.             $this->last_request = null;
  766.             $this->last_response = null;
  767.         else {
  768.             // Clear outdated headers
  769.             if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) {
  770.                 unset($this->headers[strtolower(self::CONTENT_TYPE)]);
  771.             }
  772.             if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) {
  773.                 unset($this->headers[strtolower(self::CONTENT_LENGTH)]);
  774.             }
  775.         }
  776.  
  777.         return $this;
  778.     }
  779.  
  780.     /**
  781.      * Get the last HTTP request as string
  782.      *
  783.      * @return string 
  784.      */
  785.     public function getLastRequest()
  786.     {
  787.         return $this->last_request;
  788.     }
  789.  
  790.     /**
  791.      * Get the last HTTP response received by this client
  792.      *
  793.      * If $config['storeresponse'] is set to false, or no response was
  794.      * stored yet, will return null
  795.      *
  796.      * @return Microsoft_Http_Response or null if none
  797.      */
  798.     public function getLastResponse()
  799.     {
  800.         return $this->last_response;
  801.     }
  802.  
  803.     /**
  804.      * Load the connection adapter
  805.      *
  806.      * While this method is not called more than one for a client, it is
  807.      * seperated from ->request() to preserve logic and readability
  808.      *
  809.      * @param Microsoft_Http_Client_Adapter_Interface|string$adapter 
  810.      * @return null 
  811.      * @throws Microsoft_Http_Client_Exception
  812.      */
  813.     public function setAdapter($adapter)
  814.     {
  815.         if (is_string($adapter)) {
  816.             if (!class_exists($adapter)) {
  817.                 @require_oncestr_replace('_''/'$adapter'.php' );
  818.             }
  819.  
  820.             $adapter new $adapter;
  821.         }
  822.  
  823.         if ($adapter instanceof Microsoft_Http_Client_Adapter_Interface{
  824.             /** @see Microsoft_Http_Client_Exception */
  825.             require_once 'Microsoft/Http/Client/Exception.php';
  826.             throw new Microsoft_Http_Client_Exception('Passed adapter is not a HTTP connection adapter');
  827.         }
  828.  
  829.         $this->adapter = $adapter;
  830.         $config $this->config;
  831.         unset($config['adapter']);
  832.         $this->adapter->setConfig($config);
  833.     }
  834.  
  835.     /**
  836.      * Load the connection adapter
  837.      *
  838.      * @return Microsoft_Http_Client_Adapter_Interface $adapter
  839.      */
  840.     public function getAdapter()
  841.     {
  842.         return $this->adapter;
  843.     }
  844.  
  845.     /**
  846.      * Set streaming for received data
  847.      *
  848.      * @param string|boolean$streamfile Stream file, true for temp file, false/null for no streaming
  849.      * @return Microsoft_Http_Client 
  850.      */
  851.     public function setStream($streamfile true)
  852.     {
  853.         $this->setConfig(array("output_stream" => $streamfile));
  854.         return $this;
  855.     }
  856.  
  857.     /**
  858.      * Get status of streaming for received data
  859.      * @return boolean|string
  860.      */
  861.     public function getStream()
  862.     {
  863.         return $this->config["output_stream"];
  864.     }
  865.  
  866.     /**
  867.      * Create temporary stream
  868.      *
  869.      * @return resource 
  870.      */
  871.     protected function _openTempStream()
  872.     {
  873.         $this->_stream_name $this->config['output_stream'];
  874.         if(!is_string($this->_stream_name)) {
  875.             // If name is not given, create temp name
  876.             $this->_stream_name tempnam(isset($this->config['stream_tmp_dir'])?$this->config['stream_tmp_dir']:sys_get_temp_dir(),
  877.                  'Microsoft_Http_Client');
  878.         }
  879.  
  880.         $fp fopen($this->_stream_name"w+b");
  881.         if(!$fp{
  882.                 $this->close();
  883.                 require_once 'Microsoft/Http/Client/Exception.php';
  884.                 throw new Microsoft_Http_Client_Exception("Could not open temp file $name");
  885.  
  886.         }
  887.         return $fp;
  888.     }
  889.  
  890.     /**
  891.      * Send the HTTP request and return an HTTP response object
  892.      *
  893.      * @param string $method 
  894.      * @return Microsoft_Http_Response 
  895.      * @throws Microsoft_Http_Client_Exception
  896.      */
  897.     public function request($method null)
  898.     {
  899.         if ($this->uri instanceof Microsoft_Uri_Http{
  900.             /** @see Microsoft_Http_Client_Exception */
  901.             require_once 'Microsoft/Http/Client/Exception.php';
  902.             throw new Microsoft_Http_Client_Exception('No valid URI has been passed to the client');
  903.         }
  904.  
  905.         if ($method{
  906.             $this->setMethod($method);
  907.         }
  908.         $this->redirectCounter = 0;
  909.         $response null;
  910.  
  911.         // Make sure the adapter is loaded
  912.         if ($this->adapter == null{
  913.             $this->setAdapter($this->config['adapter']);
  914.         }
  915.  
  916.         // Send the first request. If redirected, continue.
  917.         do {
  918.             // Clone the URI and add the additional GET parameters to it
  919.             $uri clone $this->uri;
  920.             if (empty($this->paramsGet)) {
  921.                 $query $uri->getQuery();
  922.                    if (empty($query)) {
  923.                        $query .= '&';
  924.                    }
  925.                 $query .= http_build_query($this->paramsGetnull'&');
  926.  
  927.                 $uri->setQuery($query);
  928.             }
  929.  
  930.             $body $this->_prepareBody();
  931.             $headers $this->_prepareHeaders();
  932.  
  933.             // check that adapter supports streaming before using it
  934.             if(is_resource($body&& !($this->adapter instanceof Microsoft_Http_Client_Adapter_Stream)) {
  935.                 /** @see Microsoft_Http_Client_Exception */
  936.                 require_once 'Microsoft/Http/Client/Exception.php';
  937.                 throw new Microsoft_Http_Client_Exception('Adapter does not support streaming');
  938.             }
  939.  
  940.             // Open the connection, send the request and read the response
  941.             $this->adapter->connect($uri->getHost()$uri->getPort(),
  942.                 ($uri->getScheme(== 'https' true false));
  943.  
  944.             if($this->config['output_stream']{
  945.                 if($this->adapter instanceof Microsoft_Http_Client_Adapter_Stream{
  946.                     $stream $this->_openTempStream();
  947.                     $this->adapter->setOutputStream($stream);
  948.                 else {
  949.                     /** @see Microsoft_Http_Client_Exception */
  950.                     require_once 'Microsoft/Http/Client/Exception.php';
  951.                     throw new Microsoft_Http_Client_Exception('Adapter does not support streaming');
  952.                 }
  953.             }
  954.  
  955.             $this->last_request = $this->adapter->write($this->method,
  956.                 $uri$this->config['httpversion']$headers$body);
  957.  
  958.             $response $this->adapter->read();
  959.             if ($response{
  960.                 /** @see Microsoft_Http_Client_Exception */
  961.                 require_once 'Microsoft/Http/Client/Exception.php';
  962.                 throw new Microsoft_Http_Client_Exception('Unable to read response, or response is empty');
  963.             }
  964.  
  965.             if($this->config['output_stream']{
  966.                 rewind($stream);
  967.                 // cleanup the adapter
  968.                 $this->adapter->setOutputStream(null);
  969.                 $response Microsoft_Http_Response_Stream::fromStream($response$stream);
  970.                 $response->setStreamName($this->_stream_name);
  971.                 if(!is_string($this->config['output_stream'])) {
  972.                     // we used temp name, will need to clean up
  973.                     $response->setCleanup(true);
  974.                 }
  975.             else {
  976.                 $response Microsoft_Http_Response::fromString($response);
  977.             }
  978.  
  979.             if ($this->config['storeresponse']{
  980.                 $this->last_response = $response;
  981.             }
  982.  
  983.             // Load cookies into cookie jar
  984.             if (isset($this->cookiejar)) {
  985.                 $this->cookiejar->addCookiesFromResponse($response$uri);
  986.             }
  987.  
  988.             // If we got redirected, look for the Location header
  989.             if ($response->isRedirect(&& ($location $response->getHeader('location'))) {
  990.  
  991.                 // Check whether we send the exact same request again, or drop the parameters
  992.                 // and send a GET request
  993.                 if ($response->getStatus(== 303 ||
  994.                    (($this->config['strictredirects']&& ($response->getStatus(== 302 ||
  995.                        $response->getStatus(== 301))) {
  996.  
  997.                     $this->resetParameters();
  998.                     $this->setMethod(self::GET);
  999.                 }
  1000.  
  1001.                 // If we got a well formed absolute URI
  1002.                 if (Microsoft_Uri_Http::check($location)) {
  1003.                     $this->setHeaders('host'null);
  1004.                     $this->setUri($location);
  1005.  
  1006.                 else {
  1007.  
  1008.                     // Split into path and query and set the query
  1009.                     if (strpos($location'?'!== false{
  1010.                         list($location$queryexplode('?'$location2);
  1011.                     else {
  1012.                         $query '';
  1013.                     }
  1014.                     $this->uri->setQuery($query);
  1015.  
  1016.                     // Else, if we got just an absolute path, set it
  1017.                     if(strpos($location'/'=== 0{
  1018.                         $this->uri->setPath($location);
  1019.  
  1020.                         // Else, assume we have a relative path
  1021.                     else {
  1022.                         // Get the current path directory, removing any trailing slashes
  1023.                         $path $this->uri->getPath();
  1024.                         $path rtrim(substr($path0strrpos($path'/'))"/");
  1025.                         $this->uri->setPath($path '/' $location);
  1026.                     }
  1027.                 }
  1028.                 ++$this->redirectCounter;
  1029.  
  1030.             else {
  1031.                 // If we didn't get any location, stop redirecting
  1032.                 break;
  1033.             }
  1034.  
  1035.         while ($this->redirectCounter < $this->config['maxredirects']);
  1036.  
  1037.         return $response;
  1038.     }
  1039.  
  1040.     /**
  1041.      * Prepare the request headers
  1042.      *
  1043.      * @return array 
  1044.      */
  1045.     protected function _prepareHeaders()
  1046.     {
  1047.         $headers array();
  1048.  
  1049.         // Set the host header
  1050.         if (isset($this->headers['host'])) {
  1051.             $host $this->uri->getHost();
  1052.  
  1053.             // If the port is not default, add it
  1054.             if ((($this->uri->getScheme(== 'http' && $this->uri->getPort(== 80||
  1055.                   ($this->uri->getScheme(== 'https' && $this->uri->getPort(== 443))) {
  1056.                 $host .= ':' $this->uri->getPort();
  1057.             }
  1058.  
  1059.             $headers["Host: {$host}";
  1060.         }
  1061.  
  1062.         // Set the connection header
  1063.         if (isset($this->headers['connection'])) {
  1064.             if ($this->config['keepalive']{
  1065.                 $headers["Connection: close";
  1066.             }
  1067.         }
  1068.  
  1069.         // Set the Accept-encoding header if not set - depending on whether
  1070.         // zlib is available or not.
  1071.         if (isset($this->headers['accept-encoding'])) {
  1072.             if (function_exists('gzinflate')) {
  1073.                 $headers['Accept-encoding: gzip, deflate';
  1074.             else {
  1075.                 $headers['Accept-encoding: identity';
  1076.             }
  1077.         }
  1078.  
  1079.         // Set the Content-Type header
  1080.         if ($this->method == self::POST &&
  1081.            (isset($this->headers[strtolower(self::CONTENT_TYPE)]&& isset($this->enctype))) {
  1082.  
  1083.             $headers[self::CONTENT_TYPE ': ' $this->enctype;
  1084.         }
  1085.  
  1086.         // Set the user agent header
  1087.         if (isset($this->headers['user-agent']&& isset($this->config['useragent'])) {
  1088.             $headers["User-Agent: {$this->config['useragent']}";
  1089.         }
  1090.  
  1091.         // Set HTTP authentication if needed
  1092.         if (is_array($this->auth)) {
  1093.             $auth self::encodeAuthHeader($this->auth['user']$this->auth['password']$this->auth['type']);
  1094.             $headers["Authorization: {$auth}";
  1095.         }
  1096.  
  1097.         // Load cookies from cookie jar
  1098.         if (isset($this->cookiejar)) {
  1099.             $cookstr $this->cookiejar->getMatchingCookies($this->uri,
  1100.                 trueMicrosoft_Http_CookieJar::COOKIE_STRING_CONCAT);
  1101.  
  1102.             if ($cookstr{
  1103.                 $headers["Cookie: {$cookstr}";
  1104.             }
  1105.         }
  1106.  
  1107.         // Add all other user defined headers
  1108.         foreach ($this->headers as $header{
  1109.             list($name$value$header;
  1110.             if (is_array($value)) {
  1111.                 $value implode(', '$value);
  1112.             }
  1113.  
  1114.             $headers["$name$value";
  1115.         }
  1116.  
  1117.         return $headers;
  1118.     }
  1119.  
  1120.     /**
  1121.      * Prepare the request body (for POST and PUT requests)
  1122.      *
  1123.      * @return string 
  1124.      * @throws Microsoft_Http_Client_Exception
  1125.      */
  1126.     protected function _prepareBody()
  1127.     {
  1128.         // According to RFC2616, a TRACE request should not have a body.
  1129.         if ($this->method == self::TRACE{
  1130.             return '';
  1131.         }
  1132.  
  1133.         if (isset($this->raw_post_data&& is_resource($this->raw_post_data)) {
  1134.             return $this->raw_post_data;
  1135.         }
  1136.         // If mbstring overloads substr and strlen functions, we have to
  1137.         // override it's internal encoding
  1138.         if (function_exists('mb_internal_encoding'&&
  1139.            ((int) ini_get('mbstring.func_overload')) 2{
  1140.  
  1141.             $mbIntEnc mb_internal_encoding();
  1142.             mb_internal_encoding('ASCII');
  1143.         }
  1144.  
  1145.         // If we have raw_post_data set, just use it as the body.
  1146.         if (isset($this->raw_post_data)) {
  1147.             $this->setHeaders(self::CONTENT_LENGTHstrlen($this->raw_post_data));
  1148.             if (isset($mbIntEnc)) {
  1149.                 mb_internal_encoding($mbIntEnc);
  1150.             }
  1151.  
  1152.             return $this->raw_post_data;
  1153.         }
  1154.  
  1155.         $body '';
  1156.  
  1157.         // If we have files to upload, force enctype to multipart/form-data
  1158.         if (count ($this->files0{
  1159.             $this->setEncType(self::ENC_FORMDATA);
  1160.         }
  1161.  
  1162.         // If we have POST parameters or files, encode and add them to the body
  1163.         if (count($this->paramsPost|| count($this->files0{
  1164.             switch($this->enctype{
  1165.                 case self::ENC_FORMDATA:
  1166.                     // Encode body as multipart/form-data
  1167.                     $boundary '---ZENDHTTPCLIENT-' md5(microtime());
  1168.                     $this->setHeaders(self::CONTENT_TYPEself::ENC_FORMDATA "; boundary={$boundary}");
  1169.  
  1170.                     // Get POST parameters and encode them
  1171.                     $params self::_flattenParametersArray($this->paramsPost);
  1172.                     foreach ($params as $pp{
  1173.                         $body .= self::encodeFormData($boundary$pp[0]$pp[1]);
  1174.                     }
  1175.  
  1176.                     // Encode files
  1177.                     foreach ($this->files as $file{
  1178.                         $fhead array(self::CONTENT_TYPE => $file['ctype']);
  1179.                         $body .= self::encodeFormData($boundary$file['formname']$file['data']$file['filename']$fhead);
  1180.                     }
  1181.  
  1182.                     $body .= "--{$boundary}--\r\n";
  1183.                     break;
  1184.  
  1185.                 case self::ENC_URLENCODED:
  1186.                     // Encode body as application/x-www-form-urlencoded
  1187.                     $this->setHeaders(self::CONTENT_TYPEself::ENC_URLENCODED);
  1188.                     $body http_build_query($this->paramsPost'''&');
  1189.                     break;
  1190.  
  1191.                 default:
  1192.                     if (isset($mbIntEnc)) {
  1193.                         mb_internal_encoding($mbIntEnc);
  1194.                     }
  1195.  
  1196.                     /** @see Microsoft_Http_Client_Exception */
  1197.                     require_once 'Microsoft/Http/Client/Exception.php';
  1198.                     throw new Microsoft_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." .
  1199.                         " Please use Microsoft_Http_Client::setRawData to send this kind of content.");
  1200.                     break;
  1201.             }
  1202.         }
  1203.  
  1204.         // Set the Content-Length if we have a body or if request is POST/PUT
  1205.         if ($body || $this->method == self::POST || $this->method == self::PUT) {
  1206.             $this->setHeaders(self::CONTENT_LENGTH, strlen($body));
  1207.         }
  1208.  
  1209.         if (isset($mbIntEnc)) {
  1210.             mb_internal_encoding($mbIntEnc);
  1211.         }
  1212.  
  1213.         return $body;
  1214.     }
  1215.  
  1216.     /**
  1217.      * Helper method that gets a possibly multi-level parameters array (get or
  1218.      * post) and flattens it.
  1219.      *
  1220.      * The method returns an array of (key, value) pairs (because keys are not
  1221.      * necessarily unique. If one of the parameters in as array, it will also
  1222.      * add a [] suffix to the key.
  1223.      *
  1224.      * This method is deprecated since Zend Framework 1.9 in favour of
  1225.      * self::_flattenParametersArray() and will be dropped in 2.0
  1226.      *
  1227.      * @deprecated since 1.9
  1228.      *
  1229.      * @param  array $parray    The parameters array
  1230.      * @param  bool  $urlencode Whether to urlencode the name and value
  1231.      * @return array
  1232.      */
  1233.     protected function _getParametersRecursive($parray, $urlencode = false)
  1234.     {
  1235.         // Issue a deprecated notice
  1236.         trigger_error("The " .  __METHOD__ . " method is deprecated and will be dropped in 2.0.",
  1237.             E_USER_NOTICE);
  1238.  
  1239.         if (! is_array($parray)) {
  1240.             return $parray;
  1241.         }
  1242.         $parameters = array();
  1243.  
  1244.         foreach ($parray as $name => $value) {
  1245.             if ($urlencode) {
  1246.                 $name = urlencode($name);
  1247.             }
  1248.  
  1249.             // If $value is an array, iterate over it
  1250.             if (is_array($value)) {
  1251.                 $name .= ($urlencode ? '%5B%5D' : '[]');
  1252.                 foreach ($value as $subval) {
  1253.                     if ($urlencode) {
  1254.                         $subval = urlencode($subval);
  1255.                     }
  1256.                     $parameters[] = array($name, $subval);
  1257.                 }
  1258.             } else {
  1259.                 if ($urlencode) {
  1260.                     $value = urlencode($value);
  1261.                 }
  1262.                 $parameters[] = array($name, $value);
  1263.             }
  1264.         }
  1265.  
  1266.         return $parameters;
  1267.     }
  1268.  
  1269.     /**
  1270.      * Attempt to detect the MIME type of a file using available extensions
  1271.      *
  1272.      * This method will try to detect the MIME type of a file. If the fileinfo
  1273.      * extension is available, it will be used. If not, the mime_magic
  1274.      * extension which is deprected but is still available in many PHP setups
  1275.      * will be tried.
  1276.      *
  1277.      * If neither extension is available, the default application/octet-stream
  1278.      * MIME type will be returned
  1279.      *
  1280.      * @param  string $file File path
  1281.      * @return string       MIME type
  1282.      */
  1283.     protected function _detectFileMimeType($file)
  1284.     {
  1285.         $type = null;
  1286.  
  1287.         // First try with fileinfo functions
  1288.         if (function_exists('finfo_open')) {
  1289.             if (self::$_fileInfoDb === null) {
  1290.                 self::$_fileInfoDb = @finfo_open(FILEINFO_MIME);
  1291.             }
  1292.  
  1293.             if (self::$_fileInfoDb) {
  1294.                 $type = finfo_file(self::$_fileInfoDb, $file);
  1295.             }
  1296.  
  1297.         } elseif (function_exists('mime_content_type')) {
  1298.             $type = mime_content_type($file);
  1299.         }
  1300.  
  1301.         // Fallback to the default application/octet-stream
  1302.         if (! $type) {
  1303.             $type = 'application/octet-stream';
  1304.         }
  1305.  
  1306.         return $type;
  1307.     }
  1308.  
  1309.     /**
  1310.      * Encode data to a multipart/form-data part suitable for a POST request.
  1311.      *
  1312.      * @param string $boundary
  1313.      * @param string $name
  1314.      * @param mixed $value
  1315.      * @param string $filename
  1316.      * @param array $headers Associative array of optional headers @example ("Content-Transfer-Encoding" => "binary")
  1317.      * @return string
  1318.      */
  1319.     public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) {
  1320.         $ret = "--{$boundary}\r\n.
  1321.             'Content-Disposition: form-data; name="' . $name .'"';
  1322.  
  1323.         if ($filename) {
  1324.             $ret .= '; filename="' . $filename . '"';
  1325.         }
  1326.         $ret .= "\r\n";
  1327.  
  1328.         foreach ($headers as $hname => $hvalue) {
  1329.             $ret .= "{$hname}: {$hvalue}\r\n";
  1330.         }
  1331.         $ret .= "\r\n";
  1332.  
  1333.         $ret .= "{$value}\r\n";
  1334.  
  1335.         return $ret;
  1336.     }
  1337.  
  1338.     /**
  1339.      * Create a HTTP authentication "Authorization:" header according to the
  1340.      * specified user, password and authentication method.
  1341.      *
  1342.      * @see http://www.faqs.org/rfcs/rfc2617.html
  1343.      * @param string $user 
  1344.      * @param string $password 
  1345.      * @param string $type 
  1346.      * @return string 
  1347.      * @throws Microsoft_Http_Client_Exception
  1348.      */
  1349.     public static function encodeAuthHeader($user$password$type self::AUTH_BASIC)
  1350.     {
  1351.         $authHeader null;
  1352.  
  1353.         switch ($type{
  1354.             case self::AUTH_BASIC:
  1355.                 // In basic authentication, the user name cannot contain ":"
  1356.                 if (strpos($user':'!== false{
  1357.                     /** @see Microsoft_Http_Client_Exception */
  1358.                     require_once 'Microsoft/Http/Client/Exception.php';
  1359.                     throw new Microsoft_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication");
  1360.                 }
  1361.  
  1362.                 $authHeader 'Basic ' base64_encode($user ':' $password);
  1363.                 break;
  1364.  
  1365.             //case self::AUTH_DIGEST:
  1366.                 /**
  1367.                  * @todo Implement digest authentication
  1368.                  */
  1369.             //    break;
  1370.  
  1371.             default:
  1372.                 /** @see Microsoft_Http_Client_Exception */
  1373.                 require_once 'Microsoft/Http/Client/Exception.php';
  1374.                 throw new Microsoft_Http_Client_Exception("Not a supported HTTP authentication type: '$type'");
  1375.         }
  1376.  
  1377.         return $authHeader;
  1378.     }
  1379.  
  1380.     /**
  1381.      * Convert an array of parameters into a flat array of (key, value) pairs
  1382.      *
  1383.      * Will flatten a potentially multi-dimentional array of parameters (such
  1384.      * as POST parameters) into a flat array of (key, value) paris. In case
  1385.      * of multi-dimentional arrays, square brackets ([]) will be added to the
  1386.      * key to indicate an array.
  1387.      *
  1388.      * @since  1.9
  1389.      *
  1390.      * @param  array  $parray 
  1391.      * @param  string $prefix 
  1392.      * @return array 
  1393.      */
  1394.     static protected function _flattenParametersArray($parray$prefix null)
  1395.     {
  1396.         if (is_array($parray)) {
  1397.             return $parray;
  1398.         }
  1399.  
  1400.         $parameters array();
  1401.  
  1402.         foreach($parray as $name => $value{
  1403.  
  1404.             // Calculate array key
  1405.             if ($prefix{
  1406.                 if (is_int($name)) {
  1407.                     $key $prefix '[]';
  1408.                 else {
  1409.                     $key $prefix "[$name]";
  1410.                 }
  1411.             else {
  1412.                 $key $name;
  1413.             }
  1414.  
  1415.             if (is_array($value)) {
  1416.                 $parameters array_merge($parametersself::_flattenParametersArray($value$key));
  1417.  
  1418.             else {
  1419.                 $parameters[array($key$value);
  1420.             }
  1421.         }
  1422.  
  1423.         return $parameters;
  1424.     }
  1425.  
  1426. }

Documentation generated on Wed, 18 May 2011 12:06:22 +0200 by phpDocumentor 1.4.3