Response.php
Current file: /usr/local/lib/php/HTTP/Request2/Response.php
Legend: executed not executed dead code

  Coverage
  Classes Functions / Methods Lines
Total
0.00% 0 / 1
13.33% 2 / 15 CRAP
31.86% 65 / 204
HTTP_Request2_Response
0.00% 0 / 1
13.33% 2 / 15 1854.41
31.86% 65 / 204
 getDefaultReasonPhrase($code = null)
0.00% 0 / 1 12
0.00% 0 / 3
 __construct($statusLine, $bodyEncoded = true, $effectiveUrl = null)
0.00% 0 / 1 3.24
70.00% 7 / 10
 parseHeaderLine($headerLine)
0.00% 0 / 1 19.81
65.71% 23 / 35
 parseCookie($cookieString)
0.00% 0 / 1 8.46
80.65% 25 / 31
 appendBody($bodyChunk)
100.00% 1 / 1 1
100.00% 2 / 2
 getEffectiveUrl()
0.00% 0 / 1 2
0.00% 0 / 1
 getStatus()
100.00% 1 / 1 1
100.00% 1 / 1
 getReasonPhrase()
0.00% 0 / 1 2
0.00% 0 / 1
 isRedirect()
0.00% 0 / 1 6
0.00% 0 / 2
 getHeader($headerName = null)
0.00% 0 / 1 3.14
75.00% 3 / 4
 getCookies()
0.00% 0 / 1 2
0.00% 0 / 1
 getBody()
0.00% 0 / 1 77.27
18.18% 4 / 22
 getVersion()
0.00% 0 / 1 2
0.00% 0 / 1
 decodeGzip($data)
0.00% 0 / 1 552
0.00% 0 / 84
 decodeDeflate($data)
0.00% 0 / 1 12
0.00% 0 / 6


       1                 : <?php                                                                                                         
       2                 : /**                                                                                                           
       3                 :  * Class representing a HTTP response                                                                         
       4                 :  *                                                                                                            
       5                 :  * PHP version 5                                                                                              
       6                 :  *                                                                                                            
       7                 :  * LICENSE:                                                                                                   
       8                 :  *                                                                                                            
       9                 :  * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>                                                       
      10                 :  * All rights reserved.                                                                                       
      11                 :  *                                                                                                            
      12                 :  * Redistribution and use in source and binary forms, with or without                                         
      13                 :  * modification, are permitted provided that the following conditions                                         
      14                 :  * are met:                                                                                                   
      15                 :  *                                                                                                            
      16                 :  *    * Redistributions of source code must retain the above copyright                                        
      17                 :  *      notice, this list of conditions and the following disclaimer.                                         
      18                 :  *    * Redistributions in binary form must reproduce the above copyright                                     
      19                 :  *      notice, this list of conditions and the following disclaimer in the                                   
      20                 :  *      documentation and/or other materials provided with the distribution.                                  
      21                 :  *    * The names of the authors may not be used to endorse or promote products                               
      22                 :  *      derived from this software without specific prior written permission.                                 
      23                 :  *                                                                                                            
      24                 :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS                                    
      25                 :  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,                                  
      26                 :  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR                                     
      27                 :  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR                                           
      28                 :  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,                                      
      29                 :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,                                        
      30                 :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR                                         
      31                 :  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY                                        
      32                 :  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING                                    
      33                 :  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS                                         
      34                 :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                               
      35                 :  *                                                                                                            
      36                 :  * @category   HTTP                                                                                           
      37                 :  * @package    HTTP_Request2                                                                                  
      38                 :  * @author     Alexey Borzov <avb@php.net>                                                                    
      39                 :  * @license    http://opensource.org/licenses/bsd-license.php New BSD License                                 
      40                 :  * @version    SVN: $Id: Response.php 317591 2011-10-01 08:37:49Z avb $                                       
      41                 :  * @link       http://pear.php.net/package/HTTP_Request2                                                      
      42                 :  */                                                                                                           
      43                 :                                                                                                               
      44                 : /**                                                                                                           
      45                 :  * Exception class for HTTP_Request2 package                                                                  
      46                 :  */                                                                                                           
      47                 : require_once 'HTTP/Request2/Exception.php';                                                                   
      48                 :                                                                                                               
      49                 : /**                                                                                                           
      50                 :  * Class representing a HTTP response                                                                         
      51                 :  *                                                                                                            
      52                 :  * The class is designed to be used in "streaming" scenario, building the                                     
      53                 :  * response as it is being received:                                                                          
      54                 :  * <code>                                                                                                     
      55                 :  * $statusLine = read_status_line();                                                                          
      56                 :  * $response = new HTTP_Request2_Response($statusLine);                                                       
      57                 :  * do {                                                                                                       
      58                 :  *     $headerLine = read_header_line();                                                                      
      59                 :  *     $response->parseHeaderLine($headerLine);                                                               
      60                 :  * } while ($headerLine != '');                                                                               
      61                 :  *                                                                                                            
      62                 :  * while ($chunk = read_body()) {                                                                             
      63                 :  *     $response->appendBody($chunk);                                                                         
      64                 :  * }                                                                                                          
      65                 :  *                                                                                                            
      66                 :  * var_dump($response->getHeader(), $response->getCookies(), $response->getBody());                           
      67                 :  * </code>                                                                                                    
      68                 :  *                                                                                                            
      69                 :  *                                                                                                            
      70                 :  * @category   HTTP                                                                                           
      71                 :  * @package    HTTP_Request2                                                                                  
      72                 :  * @author     Alexey Borzov <avb@php.net>                                                                    
      73                 :  * @version    Release: 2.0.0                                                                                 
      74                 :  * @link       http://tools.ietf.org/html/rfc2616#section-6                                                   
      75                 :  */                                                                                                           
      76                 : class HTTP_Request2_Response                                                                                  
      77                 : {                                                                                                             
      78                 :    /**                                                                                                        
      79                 :     * HTTP protocol version (e.g. 1.0, 1.1)                                                                   
      80                 :     * @var  string                                                                                            
      81                 :     */                                                                                                        
      82                 :     protected $version;                                                                                       
      83                 :                                                                                                               
      84                 :    /**                                                                                                        
      85                 :     * Status code                                                                                             
      86                 :     * @var  integer                                                                                           
      87                 :     * @link http://tools.ietf.org/html/rfc2616#section-6.1.1                                                  
      88                 :     */                                                                                                        
      89                 :     protected $code;                                                                                          
      90                 :                                                                                                               
      91                 :    /**                                                                                                        
      92                 :     * Reason phrase                                                                                           
      93                 :     * @var  string                                                                                            
      94                 :     * @link http://tools.ietf.org/html/rfc2616#section-6.1.1                                                  
      95                 :     */                                                                                                        
      96                 :     protected $reasonPhrase;                                                                                  
      97                 :                                                                                                               
      98                 :    /**                                                                                                        
      99                 :     * Effective URL (may be different from original request URL in case of redirects)                         
     100                 :     * @var  string                                                                                            
     101                 :     */                                                                                                        
     102                 :     protected $effectiveUrl;                                                                                  
     103                 :                                                                                                               
     104                 :    /**                                                                                                        
     105                 :     * Associative array of response headers                                                                   
     106                 :     * @var  array                                                                                             
     107                 :     */                                                                                                        
     108                 :     protected $headers = array();                                                                             
     109                 :                                                                                                               
     110                 :    /**                                                                                                        
     111                 :     * Cookies set in the response                                                                             
     112                 :     * @var  array                                                                                             
     113                 :     */                                                                                                        
     114                 :     protected $cookies = array();                                                                             
     115                 :                                                                                                               
     116                 :    /**                                                                                                        
     117                 :     * Name of last header processed by parseHederLine()                                                       
     118                 :     *                                                                                                         
     119                 :     * Used to handle the headers that span multiple lines                                                     
     120                 :     *                                                                                                         
     121                 :     * @var  string                                                                                            
     122                 :     */                                                                                                        
     123                 :     protected $lastHeader = null;                                                                             
     124                 :                                                                                                               
     125                 :    /**                                                                                                        
     126                 :     * Response body                                                                                           
     127                 :     * @var  string                                                                                            
     128                 :     */                                                                                                        
     129                 :     protected $body = '';                                                                                     
     130                 :                                                                                                               
     131                 :    /**                                                                                                        
     132                 :     * Whether the body is still encoded by Content-Encoding                                                   
     133                 :     *                                                                                                         
     134                 :     * cURL provides the decoded body to the callback; if we are reading from                                  
     135                 :     * socket the body is still gzipped / deflated                                                             
     136                 :     *                                                                                                         
     137                 :     * @var  bool                                                                                              
     138                 :     */                                                                                                        
     139                 :     protected $bodyEncoded;                                                                                   
     140                 :                                                                                                               
     141                 :    /**                                                                                                        
     142                 :     * Associative array of HTTP status code / reason phrase.                                                  
     143                 :     *                                                                                                         
     144                 :     * @var  array                                                                                             
     145                 :     * @link http://tools.ietf.org/html/rfc2616#section-10                                                     
     146                 :     */                                                                                                        
     147                 :     protected static $phrases = array(                                                                        
     148                 :                                                                                                               
     149                 :         // 1xx: Informational - Request received, continuing process                                          
     150                 :         100 => 'Continue',                                                                                    
     151                 :         101 => 'Switching Protocols',                                                                         
     152                 :                                                                                                               
     153                 :         // 2xx: Success - The action was successfully received, understood and                                
     154                 :         // accepted                                                                                           
     155                 :         200 => 'OK',                                                                                          
     156                 :         201 => 'Created',                                                                                     
     157                 :         202 => 'Accepted',                                                                                    
     158                 :         203 => 'Non-Authoritative Information',                                                               
     159                 :         204 => 'No Content',                                                                                  
     160                 :         205 => 'Reset Content',                                                                               
     161                 :         206 => 'Partial Content',                                                                             
     162                 :                                                                                                               
     163                 :         // 3xx: Redirection - Further action must be taken in order to complete                               
     164                 :         // the request                                                                                        
     165                 :         300 => 'Multiple Choices',                                                                            
     166                 :         301 => 'Moved Permanently',                                                                           
     167                 :         302 => 'Found',  // 1.1                                                                               
     168                 :         303 => 'See Other',                                                                                   
     169                 :         304 => 'Not Modified',                                                                                
     170                 :         305 => 'Use Proxy',                                                                                   
     171                 :         307 => 'Temporary Redirect',                                                                          
     172                 :                                                                                                               
     173                 :         // 4xx: Client Error - The request contains bad syntax or cannot be                                   
     174                 :         // fulfilled                                                                                          
     175                 :         400 => 'Bad Request',                                                                                 
     176                 :         401 => 'Unauthorized',                                                                                
     177                 :         402 => 'Payment Required',                                                                            
     178                 :         403 => 'Forbidden',                                                                                   
     179                 :         404 => 'Not Found',                                                                                   
     180                 :         405 => 'Method Not Allowed',                                                                          
     181                 :         406 => 'Not Acceptable',                                                                              
     182                 :         407 => 'Proxy Authentication Required',                                                               
     183                 :         408 => 'Request Timeout',                                                                             
     184                 :         409 => 'Conflict',                                                                                    
     185                 :         410 => 'Gone',                                                                                        
     186                 :         411 => 'Length Required',                                                                             
     187                 :         412 => 'Precondition Failed',                                                                         
     188                 :         413 => 'Request Entity Too Large',                                                                    
     189                 :         414 => 'Request-URI Too Long',                                                                        
     190                 :         415 => 'Unsupported Media Type',                                                                      
     191                 :         416 => 'Requested Range Not Satisfiable',                                                             
     192                 :         417 => 'Expectation Failed',                                                                          
     193                 :                                                                                                               
     194                 :         // 5xx: Server Error - The server failed to fulfill an apparently                                     
     195                 :         // valid request                                                                                      
     196                 :         500 => 'Internal Server Error',                                                                       
     197                 :         501 => 'Not Implemented',                                                                             
     198                 :         502 => 'Bad Gateway',                                                                                 
     199                 :         503 => 'Service Unavailable',                                                                         
     200                 :         504 => 'Gateway Timeout',                                                                             
     201                 :         505 => 'HTTP Version Not Supported',                                                                  
     202                 :         509 => 'Bandwidth Limit Exceeded',                                                                    
     203                 :                                                                                                               
     204                 :     );                                                                                                        
     205                 :                                                                                                               
     206                 :    /**                                                                                                        
     207                 :     * Returns the default reason phrase for the given code or all reason phrases                              
     208                 :     *                                                                                                         
     209                 :     * @param  int $code         Response code                                                                 
     210                 :     * @return string|array|null Default reason phrase for $code if $code is given                             
     211                 :     *                           (null if no phrase is available), array of all                                
     212                 :     *                           reason phrases if $code is null                                               
     213                 :     * @link   http://pear.php.net/bugs/18716                                                                  
     214                 :     */                                                                                                        
     215                 :     public static function getDefaultReasonPhrase($code = null)                                               
     216                 :     {                                                                                                         
     217               0 :         if (null === $code) {                                                                                 
     218               0 :             return self::$phrases;                                                                            
     219                 :         } else {                                                                                              
     220               0 :             return isset(self::$phrases[$code]) ? self::$phrases[$code] : null;                               
     221                 :         }                                                                                                     
     222                 :     }                                                                                                         
     223                 :                                                                                                               
     224                 :    /**                                                                                                        
     225                 :     * Constructor, parses the response status line                                                            
     226                 :     *                                                                                                         
     227                 :     * @param    string Response status line (e.g. "HTTP/1.1 200 OK")                                          
     228                 :     * @param    bool   Whether body is still encoded by Content-Encoding                                      
     229                 :     * @param    string Effective URL of the response                                                          
     230                 :     * @throws   HTTP_Request2_MessageException if status line is invalid according to spec                    
     231                 :     */                                                                                                        
     232                 :     public function __construct($statusLine, $bodyEncoded = true, $effectiveUrl = null)                       
     233                 :     {                                                                                                         
     234              10 :         if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) {                             
     235               0 :             throw new HTTP_Request2_MessageException(                                                         
     236               0 :                 "Malformed response: {$statusLine}",                                                          
     237                 :                 HTTP_Request2_Exception::MALFORMED_RESPONSE                                                   
     238               0 :             );                                                                                                
     239                 :         }                                                                                                     
     240              10 :         $this->version      = $m[1];                                                                          
     241              10 :         $this->code         = intval($m[2]);                                                                  
     242              10 :         $this->reasonPhrase = !empty($m[3]) ? trim($m[3]) : self::getDefaultReasonPhrase($this->code);        
     243              10 :         $this->bodyEncoded  = (bool)$bodyEncoded;                                                             
     244              10 :         $this->effectiveUrl = (string)$effectiveUrl;                                                          
     245              10 :     }                                                                                                         
     246                 :                                                                                                               
     247                 :    /**                                                                                                        
     248                 :     * Parses the line from HTTP response filling $headers array                                               
     249                 :     *                                                                                                         
     250                 :     * The method should be called after reading the line from socket or receiving                             
     251                 :     * it into cURL callback. Passing an empty string here indicates the end of                                
     252                 :     * response headers and triggers additional processing, so be sure to pass an                              
     253                 :     * empty string in the end.                                                                                
     254                 :     *                                                                                                         
     255                 :     * @param    string  Line from HTTP response                                                               
     256                 :     */                                                                                                        
     257                 :     public function parseHeaderLine($headerLine)                                                              
     258                 :     {                                                                                                         
     259              10 :         $headerLine = trim($headerLine, "\r\n");                                                              
     260                 :                                                                                                               
     261                 :         // empty string signals the end of headers, process the received ones                                 
     262              10 :         if ('' == $headerLine) {                                                                              
     263              10 :             if (!empty($this->headers['set-cookie'])) {                                                       
     264              10 :                 $cookies = is_array($this->headers['set-cookie'])?                                            
     265              10 :                            $this->headers['set-cookie']:                                                      
     266              10 :                            array($this->headers['set-cookie']);                                               
     267              10 :                 foreach ($cookies as $cookieString) {                                                         
     268              10 :                     $this->parseCookie($cookieString);                                                        
     269              10 :                 }                                                                                             
     270              10 :                 unset($this->headers['set-cookie']);                                                          
     271              10 :             }                                                                                                 
     272              10 :             foreach (array_keys($this->headers) as $k) {                                                      
     273              10 :                 if (is_array($this->headers[$k])) {                                                           
     274               0 :                     $this->headers[$k] = implode(', ', $this->headers[$k]);                                   
     275               0 :                 }                                                                                             
     276              10 :             }                                                                                                 
     277                 :                                                                                                               
     278                 :         // string of the form header-name: header value                                                       
     279              10 :         } elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) { 
     280              10 :             $name  = strtolower($m[1]);                                                                       
     281              10 :             $value = trim($m[2]);                                                                             
     282              10 :             if (empty($this->headers[$name])) {                                                               
     283              10 :                 $this->headers[$name] = $value;                                                               
     284              10 :             } else {                                                                                          
     285               0 :                 if (!is_array($this->headers[$name])) {                                                       
     286               0 :                     $this->headers[$name] = array($this->headers[$name]);                                     
     287               0 :                 }                                                                                             
     288               0 :                 $this->headers[$name][] = $value;                                                             
     289                 :             }                                                                                                 
     290              10 :             $this->lastHeader = $name;                                                                        
     291                 :                                                                                                               
     292                 :         // continuation of a previous header                                                                  
     293              10 :         } elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) {                          
     294               0 :             if (!is_array($this->headers[$this->lastHeader])) {                                               
     295               0 :                 $this->headers[$this->lastHeader] .= ' ' . trim($m[1]);                                       
     296               0 :             } else {                                                                                          
     297               0 :                 $key = count($this->headers[$this->lastHeader]) - 1;                                          
     298               0 :                 $this->headers[$this->lastHeader][$key] .= ' ' . trim($m[1]);                                 
     299                 :             }                                                                                                 
     300               0 :         }                                                                                                     
     301              10 :     }                                                                                                         
     302                 :                                                                                                               
     303                 :    /**                                                                                                        
     304                 :     * Parses a Set-Cookie header to fill $cookies array                                                       
     305                 :     *                                                                                                         
     306                 :     * @param    string    value of Set-Cookie header                                                          
     307                 :     * @link     http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
     308                 :     */                                                                                                        
     309                 :     protected function parseCookie($cookieString)                                                             
     310                 :     {                                                                                                         
     311                 :         $cookie = array(                                                                                      
     312              10 :             'expires' => null,                                                                                
     313              10 :             'domain'  => null,                                                                                
     314              10 :             'path'    => null,                                                                                
     315                 :             'secure'  => false                                                                                
     316              10 :         );                                                                                                    
     317                 :                                                                                                               
     318                 :         // Only a name=value pair                                                                             
     319              10 :         if (!strpos($cookieString, ';')) {                                                                    
     320               0 :             $pos = strpos($cookieString, '=');                                                                
     321               0 :             $cookie['name']  = trim(substr($cookieString, 0, $pos));                                          
     322               0 :             $cookie['value'] = trim(substr($cookieString, $pos + 1));                                         
     323                 :                                                                                                               
     324                 :         // Some optional parameters are supplied                                                              
     325               0 :         } else {                                                                                              
     326              10 :             $elements = explode(';', $cookieString);                                                          
     327              10 :             $pos = strpos($elements[0], '=');                                                                 
     328              10 :             $cookie['name']  = trim(substr($elements[0], 0, $pos));                                           
     329              10 :             $cookie['value'] = trim(substr($elements[0], $pos + 1));                                          
     330                 :                                                                                                               
     331              10 :             for ($i = 1; $i < count($elements); $i++) {                                                       
     332              10 :                 if (false === strpos($elements[$i], '=')) {                                                   
     333              10 :                     $elName  = trim($elements[$i]);                                                           
     334              10 :                     $elValue = null;                                                                          
     335              10 :                 } else {                                                                                      
     336              10 :                     list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));                
     337                 :                 }                                                                                             
     338              10 :                 $elName = strtolower($elName);                                                                
     339              10 :                 if ('secure' == $elName) {                                                                    
     340               0 :                     $cookie['secure'] = true;                                                                 
     341              10 :                 } elseif ('expires' == $elName) {                                                             
     342               0 :                     $cookie['expires'] = str_replace('"', '', $elValue);                                      
     343              10 :                 } elseif ('path' == $elName || 'domain' == $elName) {                                         
     344              10 :                     $cookie[$elName] = urldecode($elValue);                                                   
     345              10 :                 } else {                                                                                      
     346              10 :                     $cookie[$elName] = $elValue;                                                              
     347                 :                 }                                                                                             
     348              10 :             }                                                                                                 
     349                 :         }                                                                                                     
     350              10 :         $this->cookies[] = $cookie;                                                                           
     351              10 :     }                                                                                                         
     352                 :                                                                                                               
     353                 :    /**                                                                                                        
     354                 :     * Appends a string to the response body                                                                   
     355                 :     * @param    string                                                                                        
     356                 :     */                                                                                                        
     357                 :     public function appendBody($bodyChunk)                                                                    
     358                 :     {                                                                                                         
     359              10 :         $this->body .= $bodyChunk;                                                                            
     360              10 :     }                                                                                                         
     361                 :                                                                                                               
     362                 :    /**                                                                                                        
     363                 :     * Returns the effective URL of the response                                                               
     364                 :     *                                                                                                         
     365                 :     * This may be different from the request URL if redirects were followed.                                  
     366                 :     *                                                                                                         
     367                 :     * @return string                                                                                          
     368                 :     * @link   http://pear.php.net/bugs/bug.php?id=18412                                                       
     369                 :     */                                                                                                        
     370                 :     public function getEffectiveUrl()                                                                         
     371                 :     {                                                                                                         
     372               0 :         return $this->effectiveUrl;                                                                           
     373                 :     }                                                                                                         
     374                 :                                                                                                               
     375                 :    /**                                                                                                        
     376                 :     * Returns the status code                                                                                 
     377                 :     * @return   integer                                                                                       
     378                 :     */                                                                                                        
     379                 :     public function getStatus()                                                                               
     380                 :     {                                                                                                         
     381              10 :         return $this->code;                                                                                   
     382                 :     }                                                                                                         
     383                 :                                                                                                               
     384                 :    /**                                                                                                        
     385                 :     * Returns the reason phrase                                                                               
     386                 :     * @return   string                                                                                        
     387                 :     */                                                                                                        
     388                 :     public function getReasonPhrase()                                                                         
     389                 :     {                                                                                                         
     390               0 :         return $this->reasonPhrase;                                                                           
     391                 :     }                                                                                                         
     392                 :                                                                                                               
     393                 :    /**                                                                                                        
     394                 :     * Whether response is a redirect that can be automatically handled by HTTP_Request2                       
     395                 :     * @return   bool                                                                                          
     396                 :     */                                                                                                        
     397                 :     public function isRedirect()                                                                              
     398                 :     {                                                                                                         
     399               0 :         return in_array($this->code, array(300, 301, 302, 303, 307))                                          
     400               0 :                && isset($this->headers['location']);                                                          
     401                 :     }                                                                                                         
     402                 :                                                                                                               
     403                 :    /**                                                                                                        
     404                 :     * Returns either the named header or all response headers                                                 
     405                 :     *                                                                                                         
     406                 :     * @param    string          Name of header to return                                                      
     407                 :     * @return   string|array    Value of $headerName header (null if header is                                
     408                 :     *                           not present), array of all response headers if                                
     409                 :     *                           $headerName is null                                                           
     410                 :     */                                                                                                        
     411                 :     public function getHeader($headerName = null)                                                             
     412                 :     {                                                                                                         
     413              10 :         if (null === $headerName) {                                                                           
     414               0 :             return $this->headers;                                                                            
     415                 :         } else {                                                                                              
     416              10 :             $headerName = strtolower($headerName);                                                            
     417              10 :             return isset($this->headers[$headerName])? $this->headers[$headerName]: null;                     
     418                 :         }                                                                                                     
     419                 :     }                                                                                                         
     420                 :                                                                                                               
     421                 :    /**                                                                                                        
     422                 :     * Returns cookies set in response                                                                         
     423                 :     *                                                                                                         
     424                 :     * @return   array                                                                                         
     425                 :     */                                                                                                        
     426                 :     public function getCookies()                                                                              
     427                 :     {                                                                                                         
     428               0 :         return $this->cookies;                                                                                
     429                 :     }                                                                                                         
     430                 :                                                                                                               
     431                 :    /**                                                                                                        
     432                 :     * Returns the body of the response                                                                        
     433                 :     *                                                                                                         
     434                 :     * @return   string                                                                                        
     435                 :     * @throws   HTTP_Request2_Exception if body cannot be decoded                                             
     436                 :     */                                                                                                        
     437                 :     public function getBody()                                                                                 
     438                 :     {                                                                                                         
     439              10 :         if (0 == strlen($this->body) || !$this->bodyEncoded ||                                                
     440              10 :             !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate'))             
     441              10 :         ) {                                                                                                   
     442              10 :             return $this->body;                                                                               
     443                 :                                                                                                               
     444                 :         } else {                                                                                              
     445               0 :             if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {                    
     446               0 :                 $oldEncoding = mb_internal_encoding();                                                        
     447               0 :                 mb_internal_encoding('iso-8859-1');                                                           
     448               0 :             }                                                                                                 
     449                 :                                                                                                               
     450                 :             try {                                                                                             
     451               0 :                 switch (strtolower($this->getHeader('content-encoding'))) {                                   
     452               0 :                     case 'gzip':                                                                              
     453               0 :                         $decoded = self::decodeGzip($this->body);                                             
     454               0 :                         break;                                                                                
     455               0 :                     case 'deflate':                                                                           
     456               0 :                         $decoded = self::decodeDeflate($this->body);                                          
     457               0 :                 }                                                                                             
     458               0 :             } catch (Exception $e) {                                                                          
     459                 :             }                                                                                                 
     460                 :                                                                                                               
     461               0 :             if (!empty($oldEncoding)) {                                                                       
     462               0 :                 mb_internal_encoding($oldEncoding);                                                           
     463               0 :             }                                                                                                 
     464               0 :             if (!empty($e)) {                                                                                 
     465               0 :                 throw $e;                                                                                     
     466                 :             }                                                                                                 
     467               0 :             return $decoded;                                                                                  
     468                 :         }                                                                                                     
     469                 :     }                                                                                                         
     470                 :                                                                                                               
     471                 :    /**                                                                                                        
     472                 :     * Get the HTTP version of the response                                                                    
     473                 :     *                                                                                                         
     474                 :     * @return   string                                                                                        
     475                 :     */                                                                                                        
     476                 :     public function getVersion()                                                                              
     477                 :     {                                                                                                         
     478               0 :         return $this->version;                                                                                
     479                 :     }                                                                                                         
     480                 :                                                                                                               
     481                 :    /**                                                                                                        
     482                 :     * Decodes the message-body encoded by gzip                                                                
     483                 :     *                                                                                                         
     484                 :     * The real decoding work is done by gzinflate() built-in function, this                                   
     485                 :     * method only parses the header and checks data for compliance with                                       
     486                 :     * RFC 1952                                                                                                
     487                 :     *                                                                                                         
     488                 :     * @param    string  gzip-encoded data                                                                     
     489                 :     * @return   string  decoded data                                                                          
     490                 :     * @throws   HTTP_Request2_LogicException                                                                  
     491                 :     * @throws   HTTP_Request2_MessageException                                                                
     492                 :     * @link     http://tools.ietf.org/html/rfc1952                                                            
     493                 :     */                                                                                                        
     494                 :     public static function decodeGzip($data)                                                                  
     495                 :     {                                                                                                         
     496               0 :         $length = strlen($data);                                                                              
     497                 :         // If it doesn't look like gzip-encoded data, don't bother                                            
     498               0 :         if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) {                                        
     499               0 :             return $data;                                                                                     
     500                 :         }                                                                                                     
     501               0 :         if (!function_exists('gzinflate')) {                                                                  
     502               0 :             throw new HTTP_Request2_LogicException(                                                           
     503               0 :                 'Unable to decode body: gzip extension not available',                                        
     504                 :                 HTTP_Request2_Exception::MISCONFIGURATION                                                     
     505               0 :             );                                                                                                
     506                 :         }                                                                                                     
     507               0 :         $method = ord(substr($data, 2, 1));                                                                   
     508               0 :         if (8 != $method) {                                                                                   
     509               0 :             throw new HTTP_Request2_MessageException(                                                         
     510               0 :                 'Error parsing gzip header: unknown compression method',                                      
     511                 :                 HTTP_Request2_Exception::DECODE_ERROR                                                         
     512               0 :             );                                                                                                
     513                 :         }                                                                                                     
     514               0 :         $flags = ord(substr($data, 3, 1));                                                                    
     515               0 :         if ($flags & 224) {                                                                                   
     516               0 :             throw new HTTP_Request2_MessageException(                                                         
     517               0 :                 'Error parsing gzip header: reserved bits are set',                                           
     518                 :                 HTTP_Request2_Exception::DECODE_ERROR                                                         
     519               0 :             );                                                                                                
     520                 :         }                                                                                                     
     521                 :                                                                                                               
     522                 :         // header is 10 bytes minimum. may be longer, though.                                                 
     523               0 :         $headerLength = 10;                                                                                   
     524                 :         // extra fields, need to skip 'em                                                                     
     525               0 :         if ($flags & 4) {                                                                                     
     526               0 :             if ($length - $headerLength - 2 < 8) {                                                            
     527               0 :                 throw new HTTP_Request2_MessageException(                                                     
     528               0 :                     'Error parsing gzip header: data too short',                                              
     529                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     530               0 :                 );                                                                                            
     531                 :             }                                                                                                 
     532               0 :             $extraLength = unpack('v', substr($data, 10, 2));                                                 
     533               0 :             if ($length - $headerLength - 2 - $extraLength[1] < 8) {                                          
     534               0 :                 throw new HTTP_Request2_MessageException(                                                     
     535               0 :                     'Error parsing gzip header: data too short',                                              
     536                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     537               0 :                 );                                                                                            
     538                 :             }                                                                                                 
     539               0 :             $headerLength += $extraLength[1] + 2;                                                             
     540               0 :         }                                                                                                     
     541                 :         // file name, need to skip that                                                                       
     542               0 :         if ($flags & 8) {                                                                                     
     543               0 :             if ($length - $headerLength - 1 < 8) {                                                            
     544               0 :                 throw new HTTP_Request2_MessageException(                                                     
     545               0 :                     'Error parsing gzip header: data too short',                                              
     546                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     547               0 :                 );                                                                                            
     548                 :             }                                                                                                 
     549               0 :             $filenameLength = strpos(substr($data, $headerLength), chr(0));                                   
     550               0 :             if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {             
     551               0 :                 throw new HTTP_Request2_MessageException(                                                     
     552               0 :                     'Error parsing gzip header: data too short',                                              
     553                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     554               0 :                 );                                                                                            
     555                 :             }                                                                                                 
     556               0 :             $headerLength += $filenameLength + 1;                                                             
     557               0 :         }                                                                                                     
     558                 :         // comment, need to skip that also                                                                    
     559               0 :         if ($flags & 16) {                                                                                    
     560               0 :             if ($length - $headerLength - 1 < 8) {                                                            
     561               0 :                 throw new HTTP_Request2_MessageException(                                                     
     562               0 :                     'Error parsing gzip header: data too short',                                              
     563                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     564               0 :                 );                                                                                            
     565                 :             }                                                                                                 
     566               0 :             $commentLength = strpos(substr($data, $headerLength), chr(0));                                    
     567               0 :             if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {               
     568               0 :                 throw new HTTP_Request2_MessageException(                                                     
     569               0 :                     'Error parsing gzip header: data too short',                                              
     570                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     571               0 :                 );                                                                                            
     572                 :             }                                                                                                 
     573               0 :             $headerLength += $commentLength + 1;                                                              
     574               0 :         }                                                                                                     
     575                 :         // have a CRC for header. let's check                                                                 
     576               0 :         if ($flags & 2) {                                                                                     
     577               0 :             if ($length - $headerLength - 2 < 8) {                                                            
     578               0 :                 throw new HTTP_Request2_MessageException(                                                     
     579               0 :                     'Error parsing gzip header: data too short',                                              
     580                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     581               0 :                 );                                                                                            
     582                 :             }                                                                                                 
     583               0 :             $crcReal   = 0xffff & crc32(substr($data, 0, $headerLength));                                     
     584               0 :             $crcStored = unpack('v', substr($data, $headerLength, 2));                                        
     585               0 :             if ($crcReal != $crcStored[1]) {                                                                  
     586               0 :                 throw new HTTP_Request2_MessageException(                                                     
     587               0 :                     'Header CRC check failed',                                                                
     588                 :                     HTTP_Request2_Exception::DECODE_ERROR                                                     
     589               0 :                 );                                                                                            
     590                 :             }                                                                                                 
     591               0 :             $headerLength += 2;                                                                               
     592               0 :         }                                                                                                     
     593                 :         // unpacked data CRC and size at the end of encoded data                                              
     594               0 :         $tmp = unpack('V2', substr($data, -8));                                                               
     595               0 :         $dataCrc  = $tmp[1];                                                                                  
     596               0 :         $dataSize = $tmp[2];                                                                                  
     597                 :                                                                                                               
     598                 :         // finally, call the gzinflate() function                                                             
     599                 :         // don't pass $dataSize to gzinflate, see bugs #13135, #14370                                         
     600               0 :         $unpacked = gzinflate(substr($data, $headerLength, -8));                                              
     601               0 :         if (false === $unpacked) {                                                                            
     602               0 :             throw new HTTP_Request2_MessageException(                                                         
     603               0 :                 'gzinflate() call failed',                                                                    
     604                 :                 HTTP_Request2_Exception::DECODE_ERROR                                                         
     605               0 :             );                                                                                                
     606               0 :         } elseif ($dataSize != strlen($unpacked)) {                                                           
     607               0 :             throw new HTTP_Request2_MessageException(                                                         
     608               0 :                 'Data size check failed',                                                                     
     609                 :                 HTTP_Request2_Exception::DECODE_ERROR                                                         
     610               0 :             );                                                                                                
     611               0 :         } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {                               
     612               0 :             throw new HTTP_Request2_Exception(                                                                
     613               0 :                 'Data CRC check failed',                                                                      
     614                 :                 HTTP_Request2_Exception::DECODE_ERROR                                                         
     615               0 :             );                                                                                                
     616                 :         }                                                                                                     
     617               0 :         return $unpacked;                                                                                     
     618                 :     }                                                                                                         
     619                 :                                                                                                               
     620                 :    /**                                                                                                        
     621                 :     * Decodes the message-body encoded by deflate                                                             
     622                 :     *                                                                                                         
     623                 :     * @param    string  deflate-encoded data                                                                  
     624                 :     * @return   string  decoded data                                                                          
     625                 :     * @throws   HTTP_Request2_LogicException                                                                  
     626                 :     */                                                                                                        
     627                 :     public static function decodeDeflate($data)                                                               
     628                 :     {                                                                                                         
     629               0 :         if (!function_exists('gzuncompress')) {                                                               
     630               0 :             throw new HTTP_Request2_LogicException(                                                           
     631               0 :                 'Unable to decode body: gzip extension not available',                                        
     632                 :                 HTTP_Request2_Exception::MISCONFIGURATION                                                     
     633               0 :             );                                                                                                
     634                 :         }                                                                                                     
     635                 :         // RFC 2616 defines 'deflate' encoding as zlib format from RFC 1950,                                  
     636                 :         // while many applications send raw deflate stream from RFC 1951.                                     
     637                 :         // We should check for presence of zlib header and use gzuncompress() or                              
     638                 :         // gzinflate() as needed. See bug #15305                                                              
     639               0 :         $header = unpack('n', substr($data, 0, 2));                                                           
     640               0 :         return (0 == $header[1] % 31)? gzuncompress($data): gzinflate($data);                                 
     641                 :     }                                                                                                         
     642                 : }                                                                                                             

Generated by PHP_CodeCoverage 1.1.1 using PHP 5.3.8 and PHPUnit 3.6.7 at Sun Feb 5 13:29:22 GMT 2012.