*\r
* PHP version 5\r
*\r
- * LICENSE:\r
+ * LICENSE\r
*\r
- * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
- * All rights reserved.\r
+ * This source file is subject to BSD 3-Clause License that is bundled\r
+ * with this package in the file LICENSE and available at the URL\r
+ * https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE\r
*\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- *\r
- * * Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * * Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- * * The names of the authors may not be used to endorse or promote products\r
- * derived from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS\r
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\r
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * @category HTTP\r
- * @package HTTP_Request2\r
- * @author Alexey Borzov <avb@php.net>\r
- * @license http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version SVN: $Id: SocketWrapper.php 324935 2012-04-07 07:10:50Z avb $\r
- * @link http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package HTTP_Request2\r
+ * @author Alexey Borzov <avb@php.net>\r
+ * @copyright 2008-2014 Alexey Borzov <avb@php.net>\r
+ * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License\r
+ * @link http://pear.php.net/package/HTTP_Request2\r
*/\r
\r
/** Exception classes for HTTP_Request2 package */\r
* @category HTTP\r
* @package HTTP_Request2\r
* @author Alexey Borzov <avb@php.net>\r
- * @license http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version Release: 2.1.1\r
+ * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License\r
+ * @version Release: 2.2.1\r
* @link http://pear.php.net/package/HTTP_Request2\r
* @link http://pear.php.net/bugs/bug.php?id=19332\r
* @link http://tools.ietf.org/html/rfc1928\r
/**\r
* Class constructor, tries to establish connection\r
*\r
- * @param string $address Address for stream_socket_client() call,\r
- * e.g. 'tcp://localhost:80'\r
- * @param int $timeout Connection timeout (seconds)\r
- * @param array $sslOptions SSL context options\r
+ * @param string $address Address for stream_socket_client() call,\r
+ * e.g. 'tcp://localhost:80'\r
+ * @param int $timeout Connection timeout (seconds)\r
+ * @param array $contextOptions Context options\r
*\r
* @throws HTTP_Request2_LogicException\r
* @throws HTTP_Request2_ConnectionException\r
*/\r
- public function __construct($address, $timeout, array $sslOptions = array())\r
+ public function __construct($address, $timeout, array $contextOptions = array())\r
{\r
+ if (!empty($contextOptions)\r
+ && !isset($contextOptions['socket']) && !isset($contextOptions['ssl'])\r
+ ) {\r
+ // Backwards compatibility with 2.1.0 and 2.1.1 releases\r
+ $contextOptions = array('ssl' => $contextOptions);\r
+ }\r
$context = stream_context_create();\r
- foreach ($sslOptions as $name => $value) {\r
- if (!stream_context_set_option($context, 'ssl', $name, $value)) {\r
- throw new HTTP_Request2_LogicException(\r
- "Error setting SSL context option '{$name}'"\r
- );\r
+ foreach ($contextOptions as $wrapper => $options) {\r
+ foreach ($options as $name => $value) {\r
+ if (!stream_context_set_option($context, $wrapper, $name, $value)) {\r
+ throw new HTTP_Request2_LogicException(\r
+ "Error setting '{$wrapper}' wrapper context option '{$name}'"\r
+ );\r
+ }\r
}\r
}\r
set_error_handler(array($this, 'connectionWarningsHandler'));\r
$address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context\r
);\r
restore_error_handler();\r
- if (!$this->socket) {\r
+ // if we fail to bind to a specified local address (see request #19515),\r
+ // connection still succeeds, albeit with a warning. Throw an Exception\r
+ // with the warning text in this case as that connection is unlikely\r
+ // to be what user wants and as Curl throws an error in similar case.\r
+ if ($this->connectionWarnings) {\r
+ if ($this->socket) {\r
+ fclose($this->socket);\r
+ }\r
$error = $errstr ? $errstr : implode("\n", $this->connectionWarnings);\r
throw new HTTP_Request2_ConnectionException(\r
"Unable to connect to {$address}. Error: {$error}", 0, $errno\r
* Strips the trailing newline from the returned data, handles global\r
* request timeout. Method idea borrowed from Net_Socket PEAR package.\r
*\r
- * @param int $bufferSize buffer size to use for reading\r
+ * @param int $bufferSize buffer size to use for reading\r
+ * @param int $localTimeout timeout value to use just for this call\r
+ * (used when waiting for "100 Continue" response)\r
*\r
* @return string Available data up to the newline (not including newline)\r
* @throws HTTP_Request2_MessageException In case of timeout\r
*/\r
- public function readLine($bufferSize)\r
+ public function readLine($bufferSize, $localTimeout = null)\r
{\r
$line = '';\r
while (!feof($this->socket)) {\r
- if ($this->deadline) {\r
+ if (null !== $localTimeout) {\r
+ stream_set_timeout($this->socket, $localTimeout);\r
+ } elseif ($this->deadline) {\r
stream_set_timeout($this->socket, max($this->deadline - time(), 1));\r
}\r
+\r
$line .= @fgets($this->socket, $bufferSize);\r
- $this->checkTimeout();\r
+\r
+ if (null === $localTimeout) {\r
+ $this->checkTimeout();\r
+\r
+ } else {\r
+ $info = stream_get_meta_data($this->socket);\r
+ // reset socket timeout if we don't have request timeout specified,\r
+ // prevents further calls failing with a bogus Exception\r
+ if (!$this->deadline) {\r
+ $default = (int)@ini_get('default_socket_timeout');\r
+ stream_set_timeout($this->socket, $default > 0 ? $default : PHP_INT_MAX);\r
+ }\r
+ if ($info['timed_out']) {\r
+ throw new HTTP_Request2_MessageException(\r
+ "readLine() call timed out", HTTP_Request2_Exception::TIMEOUT\r
+ );\r
+ }\r
+ }\r
if (substr($line, -1) == "\n") {\r
return rtrim($line, "\r\n");\r
}\r