Requests.php
Current file: C:\Users\Ryan\Documents\Projects\PHP\Requests\library/Requests.php
Legend: executed not executed dead code

  Coverage
  Classes Functions / Methods Lines
Total
0.00% 0 / 1
61.54% 8 / 13 CRAP
84.00% 147 / 175
Requests
0.00% 0 / 1
68.75% 11 / 16 91.65
84.00% 147 / 175
 __construct()
100.00% 1 / 1 1
100.00% 0 / 0
 autoloader($class)
100.00% 1 / 1 3
100.00% 0 / 0
 register_autoloader()
100.00% 1 / 1 1
100.00% 0 / 0
 add_transport($transport)
0.00% 0 / 1 6
0.00% 0 / 8
 get_transport()
0.00% 0 / 1 7.01
94.12% 16 / 17
 get($url, $headers = array()
100.00% 1 / 1 1
100.00% 1 / 1
 head($url, $headers = array()
100.00% 1 / 1 1
100.00% 1 / 1
 delete($url, $headers = array()
100.00% 1 / 1 1
100.00% 1 / 1
 post($url, $headers = array()
100.00% 1 / 1 1
100.00% 1 / 1
 put($url, $headers = array()
100.00% 1 / 1 1
100.00% 1 / 1
 request($url, $headers = array()
100.00% 1 / 1 8
100.00% 41 / 41
 parse_response($headers, $url, $req_headers, $req_data, $options)
0.00% 0 / 1 19
96.30% 52 / 54
 decode_chunked($data)
100.00% 1 / 1 7
100.00% 17 / 17
 flattern($array)
100.00% 1 / 1 2
100.00% 5 / 5
 decompress($data)
0.00% 0 / 1 16.61
54.55% 6 / 11
 compatible_gzinflate($gzData)
0.00% 0 / 1 24.23
29.41% 5 / 17


       1                 : <?php                                                                                                                                                                               
       2                 : /**                                                                                                                                                                                 
       3                 :  * Requests for PHP                                                                                                                                                                 
       4                 :  *                                                                                                                                                                                  
       5                 :  * Inspired by Requests for Python.                                                                                                                                                 
       6                 :  *                                                                                                                                                                                  
       7                 :  * Based on concepts from SimplePie_File, RequestCore and WP_Http.                                                                                                                  
       8                 :  *                                                                                                                                                                                  
       9                 :  * @package Requests                                                                                                                                                                
      10                 :  */                                                                                                                                                                                 
      11                 :                                                                                                                                                                                     
      12                 : /**                                                                                                                                                                                 
      13                 :  * Requests for PHP                                                                                                                                                                 
      14                 :  *                                                                                                                                                                                  
      15                 :  * Inspired by Requests for Python.                                                                                                                                                 
      16                 :  *                                                                                                                                                                                  
      17                 :  * Based on concepts from SimplePie_File, RequestCore and WP_Http.                                                                                                                  
      18                 :  *                                                                                                                                                                                  
      19                 :  * @package Requests                                                                                                                                                                
      20                 :  */                                                                                                                                                                                 
      21                 : class Requests {                                                                                                                                                                    
      22                 :     /**                                                                                                                                                                             
      23                 :      * POST method                                                                                                                                                                  
      24                 :      *                                                                                                                                                                              
      25                 :      * @var string                                                                                                                                                                  
      26                 :      */                                                                                                                                                                             
      27                 :     const POST = 'POST';                                                                                                                                                            
      28                 :                                                                                                                                                                                     
      29                 :     /**                                                                                                                                                                             
      30                 :      * PUT method                                                                                                                                                                   
      31                 :      *                                                                                                                                                                              
      32                 :      * @var string                                                                                                                                                                  
      33                 :      */                                                                                                                                                                             
      34                 :     const PUT = 'PUT';                                                                                                                                                              
      35                 :                                                                                                                                                                                     
      36                 :     /**                                                                                                                                                                             
      37                 :      * GET method                                                                                                                                                                   
      38                 :      *                                                                                                                                                                              
      39                 :      * @var string                                                                                                                                                                  
      40                 :      */                                                                                                                                                                             
      41                 :     const GET = 'GET';                                                                                                                                                              
      42                 :                                                                                                                                                                                     
      43                 :     /**                                                                                                                                                                             
      44                 :      * HEAD method                                                                                                                                                                  
      45                 :      *                                                                                                                                                                              
      46                 :      * @var string                                                                                                                                                                  
      47                 :      */                                                                                                                                                                             
      48                 :     const HEAD = 'HEAD';                                                                                                                                                            
      49                 :                                                                                                                                                                                     
      50                 :     /**                                                                                                                                                                             
      51                 :      * DELETE method                                                                                                                                                                
      52                 :      *                                                                                                                                                                              
      53                 :      * @var string                                                                                                                                                                  
      54                 :      */                                                                                                                                                                             
      55                 :     const DELETE = 'DELETE';                                                                                                                                                        
      56                 :                                                                                                                                                                                     
      57                 :     /**                                                                                                                                                                             
      58                 :      * Current version of Requests                                                                                                                                                  
      59                 :      *                                                                                                                                                                              
      60                 :      * @var string                                                                                                                                                                  
      61                 :      */                                                                                                                                                                             
      62                 :     const VERSION = '1.6-dev';                                                                                                                                                      
      63                 :                                                                                                                                                                                     
      64                 :     /**                                                                                                                                                                             
      65                 :      * Registered transport classes                                                                                                                                                 
      66                 :      *                                                                                                                                                                              
      67                 :      * @var array                                                                                                                                                                   
      68                 :      */                                                                                                                                                                             
      69                 :     protected static $transports = array();                                                                                                                                         
      70                 :                                                                                                                                                                                     
      71                 :     /**                                                                                                                                                                             
      72                 :      * Selected transport name                                                                                                                                                      
      73                 :      *                                                                                                                                                                              
      74                 :      * Use {@see get_transport()} instead                                                                                                                                           
      75                 :      *                                                                                                                                                                              
      76                 :      * @var string|null                                                                                                                                                             
      77                 :      */                                                                                                                                                                             
      78                 :     public static $transport = null;                                                                                                                                                
      79                 :                                                                                                                                                                                     
      80                 :     /**                                                                                                                                                                             
      81                 :      * This is a static class, do not instantiate it                                                                                                                                
      82                 :      *                                                                                                                                                                              
      83                 :      * @codeCoverageIgnore                                                                                                                                                          
      84                 :      */                                                                                                                                                                             
      85                 :     private function __construct() {}                                                                                                                                               
      86                 :                                                                                                                                                                                     
      87                 :     /**                                                                                                                                                                             
      88                 :      * Autoloader for Requests                                                                                                                                                      
      89                 :      *                                                                                                                                                                              
      90                 :      * Register this with {@see register_autoloader()} if you'd like to avoid                                                                                                       
      91                 :      * having to create your own.                                                                                                                                                   
      92                 :      *                                                                                                                                                                              
      93                 :      * (You can also use `spl_autoload_register` directly if you'd prefer.)                                                                                                         
      94                 :      *                                                                                                                                                                              
      95                 :      * @codeCoverageIgnore                                                                                                                                                          
      96                 :      *                                                                                                                                                                              
      97                 :      * @param string $class Class name to load                                                                                                                                      
      98                 :      */                                                                                                                                                                             
      99                 :     public static function autoloader($class) {                                                                                                                                     
     100                 :         // Check that the class starts with "Requests"                                                                                                                              
     101                 :         if (strpos($class, 'Requests') !== 0) {                                                                                                                                     
     102                 :             return;                                                                                                                                                                 
     103                 :         }                                                                                                                                                                           
     104                 :                                                                                                                                                                                     
     105                 :         $file = str_replace('_', '/', $class);                                                                                                                                      
     106                 :         if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) {                                                                                                                
     107                 :             require_once(dirname(__FILE__) . '/' . $file . '.php');                                                                                                                 
     108                 :         }                                                                                                                                                                           
     109                 :     }                                                                                                                                                                               
     110                 :                                                                                                                                                                                     
     111                 :     /**                                                                                                                                                                             
     112                 :      * Register the built-in autoloader                                                                                                                                             
     113                 :      *                                                                                                                                                                              
     114                 :      * @codeCoverageIgnore                                                                                                                                                          
     115                 :      */                                                                                                                                                                             
     116                 :     public static function register_autoloader() {                                                                                                                                  
     117                 :         spl_autoload_register(array('Requests', 'autoloader'));                                                                                                                     
     118                 :     }                                                                                                                                                                               
     119                 :                                                                                                                                                                                     
     120                 :     /**                                                                                                                                                                             
     121                 :      * Register a transport                                                                                                                                                         
     122                 :      *                                                                                                                                                                              
     123                 :      * @param string $transport Transport class to add, must support the Requests_Transport interface                                                                               
     124                 :      */                                                                                                                                                                             
     125                 :     public static function add_transport($transport) {                                                                                                                              
     126               0 :         if (empty(self::$transports)) {                                                                                                                                             
     127               0 :             self::$transports = array(                                                                                                                                              
     128               0 :                 'Requests_Transport_cURL',                                                                                                                                          
     129               0 :                 'Requests_Transport_fsockopen',                                                                                                                                     
     130               0 :             );                                                                                                                                                                      
     131               0 :         }                                                                                                                                                                           
     132                 :                                                                                                                                                                                     
     133               0 :         self::$transports = array_merge(self::$transports, array($transport));                                                                                                      
     134               0 :     }                                                                                                                                                                               
     135                 :                                                                                                                                                                                     
     136                 :     /**                                                                                                                                                                             
     137                 :      * Get a working transport                                                                                                                                                      
     138                 :      *                                                                                                                                                                              
     139                 :      * @throws Requests_Exception If no valid transport is found (`notransport`)                                                                                                    
     140                 :      * @return Requests_Transport                                                                                                                                                   
     141                 :      */                                                                                                                                                                             
     142                 :     protected static function get_transport() {                                                                                                                                     
     143                 :         // Caching code, don't bother testing coverage                                                                                                                              
     144                 :         // @codeCoverageIgnoreStart                                                                                                                                                 
     145                 :         if (!is_null(self::$transport)) {                                                                                                                                           
     146                 :             return new self::$transport();                                                                                                                                          
     147                 :         }                                                                                                                                                                           
     148                 :         // @codeCoverageIgnoreEnd                                                                                                                                                   
     149                 :                                                                                                                                                                                     
     150               1 :         if (empty(self::$transports)) {                                                                                                                                             
     151               1 :             self::$transports = array(                                                                                                                                              
     152               1 :                 'Requests_Transport_cURL',                                                                                                                                          
     153               1 :                 'Requests_Transport_fsockopen',                                                                                                                                     
     154               1 :             );                                                                                                                                                                      
     155               1 :         }                                                                                                                                                                           
     156                 :                                                                                                                                                                                     
     157                 :         // Find us a working transport                                                                                                                                              
     158               1 :         foreach (self::$transports as $class) {                                                                                                                                     
     159               1 :             if (!class_exists($class))                                                                                                                                              
     160               1 :                 continue;                                                                                                                                                           
     161                 :                                                                                                                                                                                     
     162               1 :             $result = call_user_func(array($class, 'test'));                                                                                                                        
     163               1 :             if ($result) {                                                                                                                                                          
     164               1 :                 self::$transport = $class;                                                                                                                                          
     165               1 :                 break;                                                                                                                                                              
     166                 :             }                                                                                                                                                                       
     167               1 :         }                                                                                                                                                                           
     168               1 :         if (self::$transport === null) {                                                                                                                                            
     169               0 :             throw new Requests_Exception('No working transports found', 'notransport', self::$transports);                                                                          
     170                 :         }                                                                                                                                                                           
     171                 :                                                                                                                                                                                     
     172               1 :         return new self::$transport();                                                                                                                                              
     173                 :     }                                                                                                                                                                               
     174                 :                                                                                                                                                                                     
     175                 :     /**#@+                                                                                                                                                                          
     176                 :      * @see request()                                                                                                                                                               
     177                 :      * @param string $url                                                                                                                                                           
     178                 :      * @param array $headers                                                                                                                                                        
     179                 :      * @param array $options                                                                                                                                                        
     180                 :      * @return Requests_Response                                                                                                                                                    
     181                 :      */                                                                                                                                                                             
     182                 :     /**                                                                                                                                                                             
     183                 :      * Send a GET request                                                                                                                                                           
     184                 :      */                                                                                                                                                                             
     185                 :     public static function get($url, $headers = array(), $options = array()) {                                                                                                      
     186             120 :         return self::request($url, $headers, null, self::GET, $options);                                                                                                            
     187                 :     }                                                                                                                                                                               
     188                 :                                                                                                                                                                                     
     189                 :     /**                                                                                                                                                                             
     190                 :      * Send a HEAD request                                                                                                                                                          
     191                 :      */                                                                                                                                                                             
     192                 :     public static function head($url, $headers = array(), $options = array()) {                                                                                                     
     193               2 :         return self::request($url, $headers, null, self::HEAD, $options);                                                                                                           
     194                 :     }                                                                                                                                                                               
     195                 :                                                                                                                                                                                     
     196                 :     /**                                                                                                                                                                             
     197                 :      * Send a DELETE request                                                                                                                                                        
     198                 :      */                                                                                                                                                                             
     199                 :     public static function delete($url, $headers = array(), $options = array()) {                                                                                                   
     200               2 :         return self::request($url, $headers, null, self::DELETE, $options);                                                                                                         
     201                 :     }                                                                                                                                                                               
     202                 :     /**#@-*/                                                                                                                                                                        
     203                 :                                                                                                                                                                                     
     204                 :     /**#@+                                                                                                                                                                          
     205                 :      * @see request()                                                                                                                                                               
     206                 :      * @param string $url                                                                                                                                                           
     207                 :      * @param array $headers                                                                                                                                                        
     208                 :      * @param array $data                                                                                                                                                           
     209                 :      * @param array $options                                                                                                                                                        
     210                 :      * @return Requests_Response                                                                                                                                                    
     211                 :      */                                                                                                                                                                             
     212                 :     /**                                                                                                                                                                             
     213                 :      * Send a POST request                                                                                                                                                          
     214                 :      */                                                                                                                                                                             
     215                 :     public static function post($url, $headers = array(), $data = array(), $options = array()) {                                                                                    
     216               6 :         return self::request($url, $headers, $data, self::POST, $options);                                                                                                          
     217                 :     }                                                                                                                                                                               
     218                 :     /**                                                                                                                                                                             
     219                 :      * Send a PUT request                                                                                                                                                           
     220                 :      */                                                                                                                                                                             
     221                 :     public static function put($url, $headers = array(), $data = array(), $options = array()) {                                                                                     
     222               6 :         return self::request($url, $headers, $data, self::PUT, $options);                                                                                                           
     223                 :     }                                                                                                                                                                               
     224                 :     /**#@-*/                                                                                                                                                                        
     225                 :                                                                                                                                                                                     
     226                 :     /**                                                                                                                                                                             
     227                 :      * Main interface for HTTP requests                                                                                                                                             
     228                 :      *                                                                                                                                                                              
     229                 :      * This method initiates a request and sends it via a transport before                                                                                                          
     230                 :      * parsing.                                                                                                                                                                     
     231                 :      *                                                                                                                                                                              
     232                 :      * The `$options` parameter takes an associative array with the following                                                                                                       
     233                 :      * options:                                                                                                                                                                     
     234                 :      *                                                                                                                                                                              
     235                 :      * - `timeout`: How long should we wait for a response?                                                                                                                         
     236                 :      *    (integer, seconds, default: 10)                                                                                                                                           
     237                 :      * - `useragent`: Useragent to send to the server                                                                                                                               
     238                 :      *    (string, default: php-requests/$version)                                                                                                                                  
     239                 :      * - `follow_redirects`: Should we follow 3xx redirects?                                                                                                                        
     240                 :      *    (boolean, default: true)                                                                                                                                                  
     241                 :      * - `redirects`: How many times should we redirect before erroring?                                                                                                            
     242                 :      *    (integer, default: 10)                                                                                                                                                    
     243                 :      * - `blocking`: Should we block processing on this request?                                                                                                                    
     244                 :      *    (boolean, default: true)                                                                                                                                                  
     245                 :      * - `filename`: File to stream the body to instead.                                                                                                                            
     246                 :      *    (string|boolean, default: false)                                                                                                                                          
     247                 :      * - `auth`: Authentication handler or array of user/password details to use                                                                                                    
     248                 :      *    for Basic authentication                                                                                                                                                  
     249                 :      *    (Requests_Auth|array|boolean, default: false)                                                                                                                             
     250                 :      * - `idn`: Enable IDN parsing                                                                                                                                                  
     251                 :      *    (boolean, default: true)                                                                                                                                                  
     252                 :      * - `transport`: Custom transport. Either a class name, or a                                                                                                                   
     253                 :      *    transport object. Defaults to the first working transport from                                                                                                            
     254                 :      *    {@see getTransport()}                                                                                                                                                     
     255                 :      *    (string|Requests_Transport, default: {@see getTransport()})                                                                                                               
     256                 :      *                                                                                                                                                                              
     257                 :      * @throws Requests_Exception On invalid URLs (`nonhttp`)                                                                                                                       
     258                 :      *                                                                                                                                                                              
     259                 :      * @param string $url URL to request                                                                                                                                            
     260                 :      * @param array $headers Extra headers to send with the request                                                                                                                 
     261                 :      * @param array $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests                                                             
     262                 :      * @param string $type HTTP request type (use Requests constants)                                                                                                               
     263                 :      * @param array $options Options for the request (see description for more information)                                                                                         
     264                 :      * @return Requests_Response                                                                                                                                                    
     265                 :      */                                                                                                                                                                             
     266                 :     public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) {                                                              
     267             143 :         if (!preg_match('/^http(s)?:\/\//i', $url)) {                                                                                                                               
     268               1 :             throw new Requests_Exception('Only HTTP requests are handled.', 'nonhttp', $url);                                                                                       
     269                 :         }                                                                                                                                                                           
     270                 :         $defaults = array(                                                                                                                                                          
     271             142 :             'timeout' => 10,                                                                                                                                                        
     272             142 :             'useragent' => 'php-requests/' . self::VERSION,                                                                                                                         
     273             142 :             'redirected' => 0,                                                                                                                                                      
     274             142 :             'redirects' => 10,                                                                                                                                                      
     275             142 :             'follow_redirects' => true,                                                                                                                                             
     276             142 :             'blocking' => true,                                                                                                                                                     
     277             142 :             'type' => $type,                                                                                                                                                        
     278             142 :             'filename' => false,                                                                                                                                                    
     279             142 :             'auth' => false,                                                                                                                                                        
     280             142 :             'idn' => true,                                                                                                                                                          
     281             142 :             'hooks' => null,                                                                                                                                                        
     282             142 :             'transport' => null,                                                                                                                                                    
     283             142 :         );                                                                                                                                                                          
     284             142 :         $options = array_merge($defaults, $options);                                                                                                                                
     285                 :                                                                                                                                                                                     
     286             142 :         if (empty($options['hooks'])) {                                                                                                                                             
     287             142 :             $options['hooks'] = new Requests_Hooks();                                                                                                                               
     288             142 :         }                                                                                                                                                                           
     289                 :                                                                                                                                                                                     
     290                 :         // Special case for simple basic auth                                                                                                                                       
     291             142 :         if (is_array($options['auth'])) {                                                                                                                                           
     292               2 :             $options['auth'] = new Requests_Auth_Basic($options['auth']);                                                                                                           
     293               2 :         }                                                                                                                                                                           
     294             142 :         if ($options['auth'] !== false) {                                                                                                                                           
     295               4 :             $options['auth']->register($options['hooks']);                                                                                                                          
     296               4 :         }                                                                                                                                                                           
     297                 :                                                                                                                                                                                     
     298             142 :         $options['hooks']->dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options));                                                                 
     299                 :                                                                                                                                                                                     
     300             142 :         if ($options['idn'] !== false) {                                                                                                                                            
     301             142 :             $iri = new Requests_IRI($url);                                                                                                                                          
     302             142 :             $iri->host = Requests_IDNAEncoder::encode($iri->ihost);                                                                                                                 
     303             142 :             $url = $iri->uri;                                                                                                                                                       
     304             142 :         }                                                                                                                                                                           
     305                 :                                                                                                                                                                                     
     306             142 :         if (!empty($options['transport'])) {                                                                                                                                        
     307             141 :             $transport = $options['transport'];                                                                                                                                     
     308                 :                                                                                                                                                                                     
     309             141 :             if (is_string($options['transport'])) {                                                                                                                                 
     310             130 :                 $transport = new $transport();                                                                                                                                      
     311             130 :             }                                                                                                                                                                       
     312             141 :         }                                                                                                                                                                           
     313                 :         else {                                                                                                                                                                      
     314               1 :             $transport = self::get_transport();                                                                                                                                     
     315                 :         }                                                                                                                                                                           
     316             142 :         $response = $transport->request($url, $headers, $data, $options);                                                                                                           
     317                 :                                                                                                                                                                                     
     318             140 :         $options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options));                                                            
     319                 :                                                                                                                                                                                     
     320             140 :         return self::parse_response($response, $url, $headers, $data, $options);                                                                                                    
     321                 :     }                                                                                                                                                                               
     322                 :                                                                                                                                                                                     
     323                 :     /**                                                                                                                                                                             
     324                 :      * HTTP response parser                                                                                                                                                         
     325                 :      *                                                                                                                                                                              
     326                 :      * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`)                                                                                     
     327                 :      * @throws Requests_Exception On missing head/body separator (`noversion`)                                                                                                      
     328                 :      * @throws Requests_Exception On missing head/body separator (`toomanyredirects`)                                                                                               
     329                 :      *                                                                                                                                                                              
     330                 :      * @param string $headers Full response text including headers and body                                                                                                         
     331                 :      * @param string $url Original request URL                                                                                                                                      
     332                 :      * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects                                                           
     333                 :      * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects                                                                 
     334                 :      * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects                                                               
     335                 :      * @return Requests_Response                                                                                                                                                    
     336                 :      */                                                                                                                                                                             
     337                 :     protected static function parse_response($headers, $url, $req_headers, $req_data, $options) {                                                                                   
     338             140 :         $return = new Requests_Response();                                                                                                                                          
     339             140 :         if (!$options['blocking']) {                                                                                                                                                
     340               2 :             return $return;                                                                                                                                                         
     341                 :         }                                                                                                                                                                           
     342                 :                                                                                                                                                                                     
     343             138 :         $return->url = $url;                                                                                                                                                        
     344                 :                                                                                                                                                                                     
     345             138 :         if (!$options['filename']) {                                                                                                                                                
     346             136 :             if (strpos($headers, "\r\n\r\n") === false) {                                                                                                                           
     347                 :                 // Crap!                                                                                                                                                            
     348               1 :                 throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator');                                                                        
     349                 :             }                                                                                                                                                                       
     350                 :                                                                                                                                                                                     
     351             135 :             $headers = explode("\r\n\r\n", $headers, 2);                                                                                                                            
     352             135 :             $return->body = array_pop($headers);                                                                                                                                    
     353             135 :             $headers = $headers[0];                                                                                                                                                 
     354             135 :         }                                                                                                                                                                           
     355                 :         else {                                                                                                                                                                      
     356               2 :             $return->body = '';                                                                                                                                                     
     357                 :         }                                                                                                                                                                           
     358                 :         // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3)                                                                                                             
     359             137 :         $headers = str_replace("\r\n", "\n", $headers);                                                                                                                             
     360                 :         // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2)                                                                                      
     361             137 :         $headers = preg_replace('/\n[ \t]/', ' ', $headers);                                                                                                                        
     362             137 :         $headers = explode("\n", $headers);                                                                                                                                         
     363             137 :         preg_match('#^HTTP/1\.\d[ \t]+(\d+)#i', array_shift($headers), $matches);                                                                                                   
     364             137 :         if (empty($matches)) {                                                                                                                                                      
     365               2 :             throw new Requests_Exception('Response could not be parsed', 'noversion', $headers);                                                                                    
     366                 :         }                                                                                                                                                                           
     367             135 :         $return->status_code = (int) $matches[1];                                                                                                                                   
     368             135 :         if ($return->status_code >= 200 && $return->status_code < 300) {                                                                                                            
     369              66 :             $return->success = true;                                                                                                                                                
     370              66 :         }                                                                                                                                                                           
     371                 :                                                                                                                                                                                     
     372             135 :         foreach ($headers as $header) {                                                                                                                                             
     373             135 :             list($key, $value) = explode(':', $header, 2);                                                                                                                          
     374             135 :             $value = trim($value);                                                                                                                                                  
     375             135 :             preg_replace('#(\s+)#i', ' ', $value);                                                                                                                                  
     376             135 :             $return->headers[$key] = $value;                                                                                                                                        
     377             135 :         }                                                                                                                                                                           
     378             135 :         if (isset($return->headers['transfer-encoding'])) {                                                                                                                         
     379               5 :             $return->body = self::decode_chunked($return->body);                                                                                                                    
     380               5 :             unset($return->headers['transfer-encoding']);                                                                                                                           
     381               5 :         }                                                                                                                                                                           
     382             135 :         if (isset($return->headers['content-encoding'])) {                                                                                                                          
     383               2 :             $return->body = self::decompress($return->body);                                                                                                                        
     384               2 :         }                                                                                                                                                                           
     385                 :                                                                                                                                                                                     
     386                 :         //fsockopen and cURL compatibility                                                                                                                                          
     387             135 :         if (isset($return->headers['connection'])) {                                                                                                                                
     388             133 :             unset($return->headers['connection']);                                                                                                                                  
     389             133 :         }                                                                                                                                                                           
     390                 :                                                                                                                                                                                     
     391             135 :         if ((in_array($return->status_code, array(300, 301, 302, 303, 307)) || $return->status_code > 307 && $return->status_code < 400) && $options['follow_redirects'] === true) {
     392               7 :             if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) {                                                                            
     393               6 :                 if ($return->status_code === 303) {                                                                                                                                 
     394               0 :                     $options['type'] = Requests::GET;                                                                                                                               
     395               0 :                 }                                                                                                                                                                   
     396               6 :                 $options['redirected']++;                                                                                                                                           
     397               6 :                 $location = $return->headers['location'];                                                                                                                           
     398               6 :                 $redirected = self::request($location, $req_headers, $req_data, false, $options);                                                                                   
     399               4 :                 $redirected->history[] = $return;                                                                                                                                   
     400               4 :                 return $redirected;                                                                                                                                                 
     401                 :             }                                                                                                                                                                       
     402               3 :             elseif ($options['redirected'] >= $options['redirects']) {                                                                                                              
     403               2 :                 throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return);                                                                                    
     404                 :             }                                                                                                                                                                       
     405               1 :         }                                                                                                                                                                           
     406                 :                                                                                                                                                                                     
     407             133 :         $return->redirects = $options['redirected'];                                                                                                                                
     408                 :                                                                                                                                                                                     
     409             133 :         $options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options));                                                                  
     410             133 :         return $return;                                                                                                                                                             
     411                 :     }                                                                                                                                                                               
     412                 :                                                                                                                                                                                     
     413                 :     /**                                                                                                                                                                             
     414                 :      * Decoded a chunked body as per RFC 2616                                                                                                                                       
     415                 :      *                                                                                                                                                                              
     416                 :      * @see http://tools.ietf.org/html/rfc2616#section-3.6.1                                                                                                                        
     417                 :      * @param string $data Chunked body                                                                                                                                             
     418                 :      * @return string Decoded body                                                                                                                                                  
     419                 :      */                                                                                                                                                                             
     420                 :     protected static function decode_chunked($data) {                                                                                                                               
     421               5 :         if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($data))) {                                                                                                              
     422               1 :             return $data;                                                                                                                                                           
     423                 :         }                                                                                                                                                                           
     424                 :                                                                                                                                                                                     
     425               4 :         $decoded = '';                                                                                                                                                              
     426               4 :         $encoded = $data;                                                                                                                                                           
     427                 :                                                                                                                                                                                     
     428               4 :         while (true) {                                                                                                                                                              
     429               4 :             $is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches );                                                                                   
     430               4 :             if (!$is_chunked) {                                                                                                                                                     
     431                 :                 // Looks like it's not chunked after all                                                                                                                            
     432               1 :                 return $data;                                                                                                                                                       
     433                 :             }                                                                                                                                                                       
     434                 :                                                                                                                                                                                     
     435               4 :             $length = hexdec(trim($matches[1]));                                                                                                                                    
     436               4 :             if ($length === 0) {                                                                                                                                                    
     437                 :                 // Ignore trailer headers                                                                                                                                           
     438               1 :                 return $decoded;                                                                                                                                                    
     439                 :             }                                                                                                                                                                       
     440                 :                                                                                                                                                                                     
     441               4 :             $chunk_length = strlen($matches[0]);                                                                                                                                    
     442               4 :             $decoded .= $part = substr($encoded, $chunk_length, $length);                                                                                                           
     443               4 :             $encoded = substr($encoded, $chunk_length + $length + 2);                                                                                                               
     444                 :                                                                                                                                                                                     
     445               4 :             if (trim($encoded) === '0' || empty($encoded)) {                                                                                                                        
     446               2 :                 return $decoded;                                                                                                                                                    
     447                 :             }                                                                                                                                                                       
     448               4 :         }                                                                                                                                                                           
     449                 :                                                                                                                                                                                     
     450                 :         // We'll never actually get down here                                                                                                                                       
     451                 :         // @codeCoverageIgnoreStart                                                                                                                                                 
     452                 :     }                                                                                                                                                                               
     453                 :     // @codeCoverageIgnoreEnd                                                                                                                                                       
     454                 :                                                                                                                                                                                     
     455                 :     /**                                                                                                                                                                             
     456                 :      * Convert a key => value array to a 'key: value' array for headers                                                                                                             
     457                 :      *                                                                                                                                                                              
     458                 :      * @param array $array Dictionary of header values                                                                                                                              
     459                 :      * @return array List of headers                                                                                                                                                
     460                 :      */                                                                                                                                                                             
     461                 :     public static function flattern($array) {                                                                                                                                       
     462             130 :         $return = array();                                                                                                                                                          
     463             130 :         foreach ($array as $key => $value) {                                                                                                                                        
     464               8 :             $return[] = "$key$value";                                                                                                                                             
     465             130 :         }                                                                                                                                                                           
     466             130 :         return $return;                                                                                                                                                             
     467                 :     }                                                                                                                                                                               
     468                 :                                                                                                                                                                                     
     469                 :     /**                                                                                                                                                                             
     470                 :      * Decompress an encoded body                                                                                                                                                   
     471                 :      *                                                                                                                                                                              
     472                 :      * Implements gzip, compress and deflate. Guesses which it is by attempting                                                                                                     
     473                 :      * to decode.                                                                                                                                                                   
     474                 :      *                                                                                                                                                                              
     475                 :      * @todo Make this smarter by defaulting to whatever the headers say first                                                                                                      
     476                 :      * @param string $data Compressed data in one of the above formats                                                                                                              
     477                 :      * @return string Decompressed string                                                                                                                                           
     478                 :      */                                                                                                                                                                             
     479                 :     protected static function decompress($data) {                                                                                                                                   
     480               2 :         if (substr($data, 0, 2) !== "\x1f\x8b") {                                                                                                                                   
     481                 :             // Not actually compressed. Probably cURL ruining this for us.                                                                                                          
     482               1 :             return $data;                                                                                                                                                           
     483                 :         }                                                                                                                                                                           
     484                 :                                                                                                                                                                                     
     485               1 :         if (function_exists('gzdecode') && ($decoded = gzdecode($data)) !== false) {                                                                                                
     486               0 :             return $decoded;                                                                                                                                                        
     487                 :         }                                                                                                                                                                           
     488               1 :         elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) {                                                                                         
     489               0 :             return $decoded;                                                                                                                                                        
     490                 :         }                                                                                                                                                                           
     491               1 :         elseif (($decoded = self::compatible_gzinflate($data)) !== false) {                                                                                                         
     492               1 :             return $decoded;                                                                                                                                                        
     493                 :         }                                                                                                                                                                           
     494               0 :         elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) {                                                                                   
     495               0 :             return $decoded;                                                                                                                                                        
     496                 :         }                                                                                                                                                                           
     497                 :                                                                                                                                                                                     
     498               0 :         return $data;                                                                                                                                                               
     499                 :     }                                                                                                                                                                               
     500                 :                                                                                                                                                                                     
     501                 :     /**                                                                                                                                                                             
     502                 :      * Decompress deflated string while staying compatible with the majority of servers.                                                                                            
     503                 :      *                                                                                                                                                                              
     504                 :      * Certain servers will return deflated data with headers which PHP's gziniflate()                                                                                              
     505                 :      * function cannot handle out of the box. The following function lifted from                                                                                                    
     506                 :      * http://au2.php.net/manual/en/function.gzinflate.php#77336 will attempt to deflate                                                                                            
     507                 :      * the various return forms used.                                                                                                                                               
     508                 :      *                                                                                                                                                                              
     509                 :      * @link http://au2.php.net/manual/en/function.gzinflate.php#77336                                                                                                              
     510                 :      *                                                                                                                                                                              
     511                 :      * @param string $gzData String to decompress.                                                                                                                                  
     512                 :      * @return string|bool False on failure.                                                                                                                                        
     513                 :      */                                                                                                                                                                             
     514                 :     protected static function compatible_gzinflate($gzData) {                                                                                                                       
     515               1 :         if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) {                                                                                                                            
     516               1 :             $i = 10;                                                                                                                                                                
     517               1 :             $flg = ord( substr($gzData, 3, 1) );                                                                                                                                    
     518               1 :             if ( $flg > 0 ) {                                                                                                                                                       
     519               0 :                 if ( $flg & 4 ) {                                                                                                                                                   
     520               0 :                     list($xlen) = unpack('v', substr($gzData, $i, 2) );                                                                                                             
     521               0 :                     $i = $i + 2 + $xlen;                                                                                                                                            
     522               0 :                 }                                                                                                                                                                   
     523               0 :                 if ( $flg & 8 )                                                                                                                                                     
     524               0 :                     $i = strpos($gzData, "\0", $i) + 1;                                                                                                                             
     525               0 :                 if ( $flg & 16 )                                                                                                                                                    
     526               0 :                     $i = strpos($gzData, "\0", $i) + 1;                                                                                                                             
     527               0 :                 if ( $flg & 2 )                                                                                                                                                     
     528               0 :                     $i = $i + 2;                                                                                                                                                    
     529               0 :             }                                                                                                                                                                       
     530               1 :             return gzinflate( substr($gzData, $i, -8) );                                                                                                                            
     531                 :         } else {                                                                                                                                                                    
     532               0 :             return false;                                                                                                                                                           
     533                 :         }                                                                                                                                                                           
     534                 :     }                                                                                                                                                                               

Generated by PHP_CodeCoverage 1.1.1 using PHP 5.3.8 and PHPUnit 3.6.10 at Wed Feb 8 15:08:23 EST 2012.