includes/http.php
changeset 1113 000791abdc7e
parent 1086 6a59951b70e4
child 1135 56c0abbdad3e
equal deleted inserted replaced
1112:679916c80599 1113:000791abdc7e
   446       $buffer = $this->_read_until_newlines($this->socket);
   446       $buffer = $this->_read_until_newlines($this->socket);
   447       $this->state = 3;
   447       $this->state = 3;
   448       $this->_parse_response_code($buffer);
   448       $this->_parse_response_code($buffer);
   449       $this->response = $buffer;
   449       $this->response = $buffer;
   450     }
   450     }
       
   451     // obey redirects
       
   452     $i = 0;
       
   453     while ( $i < 20 )
       
   454     {
       
   455       $incoming_headers = $this->get_response_headers_array();
       
   456       if ( !$incoming_headers )
       
   457         break;
       
   458       if ( isset($incoming_headers['Location']) )
       
   459       {
       
   460         // we've been redirected...
       
   461         $new_uri = $this->_resolve_uri($incoming_headers['Location']);
       
   462         if ( !$new_uri )
       
   463         {
       
   464           // ... bad URI, ignore Location header.
       
   465           break;
       
   466         }
       
   467         // change location
       
   468         $this->host = $new_uri['host'];
       
   469         $this->port = $new_uri['port'];
       
   470         $this->uri  = $new_uri['uri'];
       
   471         $get = '';
       
   472         
       
   473         // reset
       
   474         $this->sock_close($this->socket);
       
   475         $this->_sock_open($this->socket);
       
   476         $this->_write_request($this->socket, $headers, $cookies, $get, $post);
       
   477         $buffer = $this->_read_until_newlines($this->socket);
       
   478         $this->state = 3;
       
   479         $this->_parse_response_code($buffer);
       
   480         $this->response = $buffer;
       
   481         $i++;
       
   482       }
       
   483       else
       
   484       {
       
   485         break;
       
   486       }
       
   487     }
       
   488     if ( $i == 20 )
       
   489     {
       
   490       throw new Exception(__METHOD__ . ": Redirect trap. Request_HTTP doesn't do cookies, btw.");
       
   491     }
       
   492     
   451     if ( $this->state == 3 )
   493     if ( $this->state == 3 )
   452     {
   494     {
   453       // Determine transfer encoding
   495       // Determine transfer encoding
   454       $is_chunked = preg_match("/Transfer-Encoding: (chunked)\r?\n/", $this->response);
   496       $is_chunked = preg_match("/Transfer-Encoding: (chunked)\r?\n/", $this->response);
   455       
   497       if ( preg_match("/^Content-Length: ([0-9]+)[\s]*$/mi", $this->response, $match) && !$is_chunked )
   456       $buffer = '';
   498       {
   457       while ( !feof($this->socket) )
   499         $size = intval($match[1]);
   458       {
   500         if ( $this->debug )
   459         $part = fgets($this->socket, 1024);
       
   460         if ( $is_chunked && preg_match("/^([a-f0-9]+)\x0D\x0A$/", $part, $match) )
       
   461         {
   501         {
   462           $chunklen = hexdec($match[1]);
   502           echo "Pulling response using fread(), size $size\n";
   463           $part = ( $chunklen > 0 ) ? fread($this->socket, $chunklen) : '';
       
   464           // remove the last newline from $part
       
   465           $part = preg_replace("/\r?\n\$/m", "", $part);
       
   466         }
   503         }
   467         $buffer .= $part;
   504         $this->response .= fread($this->socket, $size);
   468       }
   505       }
   469       $this->response .= $buffer;
   506       else
       
   507       {
       
   508         if ( $this->debug )
       
   509           echo "Pulling response using chunked handler\n";
       
   510           
       
   511         $buffer = '';
       
   512         while ( !feof($this->socket) )
       
   513         {
       
   514           $part = fgets($this->socket, 1024);
       
   515           if ( $is_chunked && preg_match("/^([a-f0-9]+)\x0D\x0A$/", $part, $match) )
       
   516           {
       
   517             $chunklen = hexdec($match[1]);
       
   518             $part = ( $chunklen > 0 ) ? fread($this->socket, $chunklen) : '';
       
   519             // remove the last newline from $part
       
   520             $part = preg_replace("/\r?\n\$/", "", $part);
       
   521           }
       
   522           $buffer .= $part;
       
   523         }
       
   524         $this->response .= $buffer;
       
   525       }
   470     }
   526     }
   471     $this->state = 4;
   527     $this->state = 4;
   472     
   528     
   473     $this->sock_close($this->socket);
   529     $this->sock_close($this->socket);
   474     $this->socket = false;
   530     $this->socket = false;
   637     $this->state = 0;
   693     $this->state = 0;
   638     return ($bandwidth_exceeded) ? false : true;
   694     return ($bandwidth_exceeded) ? false : true;
   639   }
   695   }
   640   
   696   
   641   /**
   697   /**
       
   698    * Resolves, based on current settings and URI, a URI string to an array consisting of a host, port, and new URI. Returns false on error.
       
   699    * @param string
       
   700    * @return array
       
   701    */
       
   702   
       
   703   function _resolve_uri($uri)
       
   704   {
       
   705     // long ass regexp w00t
       
   706     if ( !preg_match('#^(?:https?://((?:(?:[a-z0-9-]+\.)*)(?:[a-z0-9-]+)|\[[a-f0-9:]+\])(?::([0-9]+))?)?(/)(.*)$#i', $uri, $match) )
       
   707     {
       
   708       // bad target URI
       
   709       return false;
       
   710     }
       
   711     $hostpart = $match[1];
       
   712     if ( empty($hostpart) )
       
   713     {
       
   714       // use existing host
       
   715       $host = $this->host;
       
   716       $port = $this->port;
       
   717     }
       
   718     else
       
   719     {
       
   720       $host = $match[1];
       
   721       $port = empty($match[2]) ? 80 : intval($match[2]);
       
   722     }
       
   723     // is this an absolute URI, or relative?
       
   724     if ( empty($match[3]) )
       
   725     {
       
   726       // relative
       
   727       $uri = dirname($this->uri) . $match[4];
       
   728     }
       
   729     else
       
   730     {
       
   731       // absolute
       
   732       $uri = '/' . $match[4];
       
   733     }
       
   734     return array(
       
   735         'host' => $host,
       
   736         'port' => $port,
       
   737         'uri'  => $uri
       
   738       );
       
   739   }
       
   740   
       
   741   /**
   642    * Returns only the response headers.
   742    * Returns only the response headers.
   643    * @return string
   743    * @return string
   644    */
   744    */
   645   
   745   
   646   function get_response_headers()
   746   function get_response_headers()
   650       return $this->response;
   750       return $this->response;
   651     }
   751     }
   652     else if ( $this->state == 4 )
   752     else if ( $this->state == 4 )
   653     {
   753     {
   654       $pos_end = strpos($this->response, "\r\n\r\n");
   754       $pos_end = strpos($this->response, "\r\n\r\n");
   655       $data = substr($this->response, 0, $pos_start);
   755       if ( empty($pos_end) )
       
   756       {
       
   757         $pos_end = strpos($this->response, "\n\n");
       
   758       }
       
   759       $data = substr($this->response, 0, $pos_end);
   656       return $data;
   760       return $data;
   657     }
   761     }
   658     else
   762     else
   659     {
   763     {
   660       $this->_send_request_headers_only();
   764       $this->_send_request_headers_only();
   686   
   790   
   687   function get_response_body()
   791   function get_response_body()
   688   {
   792   {
   689     $data = $this->get_response();
   793     $data = $this->get_response();
   690     $pos_start = strpos($data, "\r\n\r\n") + 4;
   794     $pos_start = strpos($data, "\r\n\r\n") + 4;
       
   795     if ( $pos_start == 4 )
       
   796     {
       
   797       $pos_start = strpos($data, "\n\n") + 4;
       
   798     }
   691     $data = substr($data, $pos_start);
   799     $data = substr($data, $pos_start);
   692     return $data;
   800     return $data;
   693   }
   801   }
   694   
   802   
   695   /**
   803   /**
   721   
   829   
   722   function _fputs($socket, $data)
   830   function _fputs($socket, $data)
   723   {
   831   {
   724     if ( $this->debug )
   832     if ( $this->debug )
   725       echo htmlspecialchars($data);
   833       echo htmlspecialchars($data);
       
   834     
   726     return fputs($socket, $data);
   835     return fputs($socket, $data);
   727   }
   836   }
   728   
   837   
   729   /**
   838   /**
   730    * Internal function to stringify cookies, headers, get, and post.
   839    * Internal function to stringify cookies, headers, get, and post.
   791     }
   900     }
   792   }
   901   }
   793   
   902   
   794 }
   903 }
   795 
   904 
   796 ?>