# HG changeset patch # User Dan # Date 1252763799 14400 # Node ID 000791abdc7eb2b666526325053e4db1416d60be # Parent 679916c805994414fd118af7b5a50aef067885e1 Request_HTTP: Fixed get_response_body(), added HTTP redirect support, and added support for Content-Length. diff -r 679916c80599 -r 000791abdc7e includes/http.php --- a/includes/http.php Fri Sep 11 09:57:42 2009 -0400 +++ b/includes/http.php Sat Sep 12 09:56:39 2009 -0400 @@ -448,25 +448,81 @@ $this->_parse_response_code($buffer); $this->response = $buffer; } + // obey redirects + $i = 0; + while ( $i < 20 ) + { + $incoming_headers = $this->get_response_headers_array(); + if ( !$incoming_headers ) + break; + if ( isset($incoming_headers['Location']) ) + { + // we've been redirected... + $new_uri = $this->_resolve_uri($incoming_headers['Location']); + if ( !$new_uri ) + { + // ... bad URI, ignore Location header. + break; + } + // change location + $this->host = $new_uri['host']; + $this->port = $new_uri['port']; + $this->uri = $new_uri['uri']; + $get = ''; + + // reset + $this->sock_close($this->socket); + $this->_sock_open($this->socket); + $this->_write_request($this->socket, $headers, $cookies, $get, $post); + $buffer = $this->_read_until_newlines($this->socket); + $this->state = 3; + $this->_parse_response_code($buffer); + $this->response = $buffer; + $i++; + } + else + { + break; + } + } + if ( $i == 20 ) + { + throw new Exception(__METHOD__ . ": Redirect trap. Request_HTTP doesn't do cookies, btw."); + } + if ( $this->state == 3 ) { // Determine transfer encoding $is_chunked = preg_match("/Transfer-Encoding: (chunked)\r?\n/", $this->response); - - $buffer = ''; - while ( !feof($this->socket) ) + if ( preg_match("/^Content-Length: ([0-9]+)[\s]*$/mi", $this->response, $match) && !$is_chunked ) { - $part = fgets($this->socket, 1024); - if ( $is_chunked && preg_match("/^([a-f0-9]+)\x0D\x0A$/", $part, $match) ) + $size = intval($match[1]); + if ( $this->debug ) { - $chunklen = hexdec($match[1]); - $part = ( $chunklen > 0 ) ? fread($this->socket, $chunklen) : ''; - // remove the last newline from $part - $part = preg_replace("/\r?\n\$/m", "", $part); + echo "Pulling response using fread(), size $size\n"; } - $buffer .= $part; + $this->response .= fread($this->socket, $size); } - $this->response .= $buffer; + else + { + if ( $this->debug ) + echo "Pulling response using chunked handler\n"; + + $buffer = ''; + while ( !feof($this->socket) ) + { + $part = fgets($this->socket, 1024); + if ( $is_chunked && preg_match("/^([a-f0-9]+)\x0D\x0A$/", $part, $match) ) + { + $chunklen = hexdec($match[1]); + $part = ( $chunklen > 0 ) ? fread($this->socket, $chunklen) : ''; + // remove the last newline from $part + $part = preg_replace("/\r?\n\$/", "", $part); + } + $buffer .= $part; + } + $this->response .= $buffer; + } } $this->state = 4; @@ -639,6 +695,50 @@ } /** + * 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. + * @param string + * @return array + */ + + function _resolve_uri($uri) + { + // long ass regexp w00t + if ( !preg_match('#^(?:https?://((?:(?:[a-z0-9-]+\.)*)(?:[a-z0-9-]+)|\[[a-f0-9:]+\])(?::([0-9]+))?)?(/)(.*)$#i', $uri, $match) ) + { + // bad target URI + return false; + } + $hostpart = $match[1]; + if ( empty($hostpart) ) + { + // use existing host + $host = $this->host; + $port = $this->port; + } + else + { + $host = $match[1]; + $port = empty($match[2]) ? 80 : intval($match[2]); + } + // is this an absolute URI, or relative? + if ( empty($match[3]) ) + { + // relative + $uri = dirname($this->uri) . $match[4]; + } + else + { + // absolute + $uri = '/' . $match[4]; + } + return array( + 'host' => $host, + 'port' => $port, + 'uri' => $uri + ); + } + + /** * Returns only the response headers. * @return string */ @@ -652,7 +752,11 @@ else if ( $this->state == 4 ) { $pos_end = strpos($this->response, "\r\n\r\n"); - $data = substr($this->response, 0, $pos_start); + if ( empty($pos_end) ) + { + $pos_end = strpos($this->response, "\n\n"); + } + $data = substr($this->response, 0, $pos_end); return $data; } else @@ -688,6 +792,10 @@ { $data = $this->get_response(); $pos_start = strpos($data, "\r\n\r\n") + 4; + if ( $pos_start == 4 ) + { + $pos_start = strpos($data, "\n\n") + 4; + } $data = substr($data, $pos_start); return $data; } @@ -723,6 +831,7 @@ { if ( $this->debug ) echo htmlspecialchars($data); + return fputs($socket, $data); } @@ -793,4 +902,3 @@ } -?>