diff options
Diffstat (limited to 'libs/Zend/Http/Client/Adapter/Socket.php')
-rw-r--r-- | libs/Zend/Http/Client/Adapter/Socket.php | 175 |
1 files changed, 127 insertions, 48 deletions
diff --git a/libs/Zend/Http/Client/Adapter/Socket.php b/libs/Zend/Http/Client/Adapter/Socket.php index 13427c749f..4f3d41722d 100644 --- a/libs/Zend/Http/Client/Adapter/Socket.php +++ b/libs/Zend/Http/Client/Adapter/Socket.php @@ -16,19 +16,23 @@ * @category Zend * @package Zend_Http * @subpackage Client_Adapter - * @version $Id: Socket.php 17124 2009-07-26 09:46:42Z shahar $ - * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id: Socket.php 21778 2010-04-06 11:19:35Z shahar $ + * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ /** * @see Zend_Uri_Http */ -require_once 'Zend/Uri/Http.php'; +// require_once 'Zend/Uri/Http.php'; /** * @see Zend_Http_Client_Adapter_Interface */ -require_once 'Zend/Http/Client/Adapter/Interface.php'; +// require_once 'Zend/Http/Client/Adapter/Interface.php'; +/** + * @see Zend_Http_Client_Adapter_Stream + */ +// require_once 'Zend/Http/Client/Adapter/Stream.php'; /** * A sockets based (stream_socket_client) adapter class for Zend_Http_Client. Can be used @@ -37,10 +41,10 @@ require_once 'Zend/Http/Client/Adapter/Interface.php'; * @category Zend * @package Zend_Http * @subpackage Client_Adapter - * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interface +class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interface, Zend_Http_Client_Adapter_Stream { /** * The socket for server connection @@ -57,6 +61,13 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf protected $connected_to = array(null, null); /** + * Stream for storing output + * + * @var resource + */ + protected $out_stream = null; + + /** * Parameters array * * @var array @@ -65,7 +76,8 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf 'persistent' => false, 'ssltransport' => 'ssl', 'sslcert' => null, - 'sslpassphrase' => null + 'sslpassphrase' => null, + 'sslusecontext' => false ); /** @@ -101,7 +113,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf $config = $config->toArray(); } elseif (! is_array($config)) { - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception( 'Array or Zend_Config object expected, got ' . gettype($config) ); @@ -112,7 +124,17 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf } } - /** + /** + * Retrieve the array of all configuration options + * + * @return array + */ + public function getConfig() + { + return $this->config; + } + + /** * Set the stream context for the TCP connection to the server * * Can accept either a pre-existing stream context resource, or an array @@ -135,7 +157,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf } else { // Invalid parameter - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception( "Expecting either a stream context resource or array, got " . gettype($context) ); @@ -180,18 +202,18 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf // Now, if we are not connected, connect if (! is_resource($this->socket) || ! $this->config['keepalive']) { $context = $this->getStreamContext(); - if ($secure) { + if ($secure || $this->config['sslusecontext']) { if ($this->config['sslcert'] !== null) { if (! stream_context_set_option($context, 'ssl', 'local_cert', $this->config['sslcert'])) { - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception('Unable to set sslcert option'); } } if ($this->config['sslpassphrase'] !== null) { if (! stream_context_set_option($context, 'ssl', 'passphrase', $this->config['sslpassphrase'])) { - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception('Unable to set sslpassphrase option'); } } @@ -209,14 +231,14 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf if (! $this->socket) { $this->close(); - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception( 'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr); } // Set the stream timeout if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) { - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception('Unable to set the connection timeout'); } @@ -239,14 +261,14 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf { // Make sure we're properly connected if (! $this->socket) { - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception('Trying to write but we are not connected'); } $host = $uri->getHost(); $host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host; if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) { - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host'); } @@ -262,14 +284,25 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf $request .= "$v\r\n"; } - // Add the request body - $request .= "\r\n" . $body; - + if(is_resource($body)) { + $request .= "\r\n"; + } else { + // Add the request body + $request .= "\r\n" . $body; + } + // Send the request if (! @fwrite($this->socket, $request)) { - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception('Error writing request to server'); } + + if(is_resource($body)) { + if(stream_copy_to_stream($body, $this->socket) == 0) { + // require_once 'Zend/Http/Client/Adapter/Exception.php'; + throw new Zend_Http_Client_Adapter_Exception('Error writing request to server'); + } + } return $request; } @@ -284,6 +317,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf // First, read headers only $response = ''; $gotStatus = false; + $stream = !empty($this->config['stream']); while (($line = @fgets($this->socket)) !== false) { $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false); @@ -292,7 +326,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf if (rtrim($line) === '') break; } } - + $this->_checkSocketReadTimeout(); $statusCode = Zend_Http_Response::extractCode($response); @@ -319,7 +353,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf // If we got a 'transfer-encoding: chunked' header if (isset($headers['transfer-encoding'])) { - + if (strtolower($headers['transfer-encoding']) == 'chunked') { do { @@ -332,7 +366,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf $chunksize = trim($line); if (! ctype_xdigit($chunksize)) { $this->close(); - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception('Invalid chunk size "' . $chunksize . '" unable to read chunked body'); } @@ -347,45 +381,71 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf $current_pos = ftell($this->socket); if ($current_pos >= $read_to) break; - $line = @fread($this->socket, $read_to - $current_pos); - if ($line === false || strlen($line) === 0) { - $this->_checkSocketReadTimeout(); - break; + if($this->out_stream) { + if(stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) { + $this->_checkSocketReadTimeout(); + break; + } } else { - $chunk .= $line; + $line = @fread($this->socket, $read_to - $current_pos); + if ($line === false || strlen($line) === 0) { + $this->_checkSocketReadTimeout(); + break; + } + $chunk .= $line; } - } while (! feof($this->socket)); $chunk .= @fgets($this->socket); $this->_checkSocketReadTimeout(); - $response .= $chunk; + if(!$this->out_stream) { + $response .= $chunk; + } } while ($chunksize > 0); - } else { $this->close(); throw new Zend_Http_Client_Adapter_Exception('Cannot handle "' . $headers['transfer-encoding'] . '" transfer encoding'); } - + + // We automatically decode chunked-messages when writing to a stream + // this means we have to disallow the Zend_Http_Response to do it again + if ($this->out_stream) { + $response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response); + } // Else, if we got the content-length header, read this number of bytes } elseif (isset($headers['content-length'])) { + // If we got more than one Content-Length header (see ZF-9404) use + // the last value sent + if (is_array($headers['content-length'])) { + $contentLength = $headers['content-length'][count($headers['content-length']) - 1]; + } else { + $contentLength = $headers['content-length']; + } + $current_pos = ftell($this->socket); $chunk = ''; - for ($read_to = $current_pos + $headers['content-length']; + for ($read_to = $current_pos + $contentLength; $read_to > $current_pos; $current_pos = ftell($this->socket)) { - $chunk = @fread($this->socket, $read_to - $current_pos); - if ($chunk === false || strlen($chunk) === 0) { - $this->_checkSocketReadTimeout(); - break; - } + if($this->out_stream) { + if(@stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $chunk = @fread($this->socket, $read_to - $current_pos); + if ($chunk === false || strlen($chunk) === 0) { + $this->_checkSocketReadTimeout(); + break; + } - $response .= $chunk; + $response .= $chunk; + } // Break if the connection ended prematurely if (feof($this->socket)) break; @@ -395,12 +455,19 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf } else { do { - $buff = @fread($this->socket, 8192); - if ($buff === false || strlen($buff) === 0) { - $this->_checkSocketReadTimeout(); - break; - } else { - $response .= $buff; + if($this->out_stream) { + if(@stream_copy_to_stream($this->socket, $this->out_stream) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $buff = @fread($this->socket, 8192); + if ($buff === false || strlen($buff) === 0) { + $this->_checkSocketReadTimeout(); + break; + } else { + $response .= $buff; + } } } while (feof($this->socket) === false); @@ -440,7 +507,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf $timedout = $info['timed_out']; if ($timedout) { $this->close(); - require_once 'Zend/Http/Client/Adapter/Exception.php'; + // require_once 'Zend/Http/Client/Adapter/Exception.php'; throw new Zend_Http_Client_Adapter_Exception( "Read timed out after {$this->config['timeout']} seconds", Zend_Http_Client_Adapter_Exception::READ_TIMEOUT @@ -448,7 +515,19 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf } } } - + + /** + * Set output stream for the response + * + * @param resource $stream + * @return Zend_Http_Client_Adapter_Socket + */ + public function setOutputStream($stream) + { + $this->out_stream = $stream; + return $this; + } + /** * Destructor: make sure the socket is disconnected * |