Updating external libraries for net access
This commit is contained in:
parent
ce37edc1b0
commit
c51086b302
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Request2.php 308735 2011-02-27 20:31:28Z avb $
|
||||
* @version SVN: $Id: Request2.php 324936 2012-04-07 07:49:03Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -57,7 +57,9 @@ require_once 'HTTP/Request2/Exception.php';
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @version Release: 2.0.0RC1
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
* @link http://tools.ietf.org/html/rfc2616#section-5
|
||||
*/
|
||||
class HTTP_Request2 implements SplSubject
|
||||
@ -156,6 +158,7 @@ class HTTP_Request2 implements SplSubject
|
||||
'proxy_user' => '',
|
||||
'proxy_password' => '',
|
||||
'proxy_auth_scheme' => self::AUTH_BASIC,
|
||||
'proxy_type' => 'http',
|
||||
|
||||
'ssl_verify_peer' => true,
|
||||
'ssl_verify_host' => true,
|
||||
@ -217,12 +220,13 @@ class HTTP_Request2 implements SplSubject
|
||||
*
|
||||
* Also sets a default value for User-Agent header.
|
||||
*
|
||||
* @param string|Net_Url2 Request URL
|
||||
* @param string Request method
|
||||
* @param array Configuration for this Request instance
|
||||
* @param string|Net_Url2 $url Request URL
|
||||
* @param string $method Request method
|
||||
* @param array $config Configuration for this Request instance
|
||||
*/
|
||||
public function __construct($url = null, $method = self::METHOD_GET, array $config = array())
|
||||
{
|
||||
public function __construct(
|
||||
$url = null, $method = self::METHOD_GET, array $config = array()
|
||||
) {
|
||||
$this->setConfig($config);
|
||||
if (!empty($url)) {
|
||||
$this->setUrl($url);
|
||||
@ -230,9 +234,10 @@ class HTTP_Request2 implements SplSubject
|
||||
if (!empty($method)) {
|
||||
$this->setMethod($method);
|
||||
}
|
||||
$this->setHeader('user-agent', 'HTTP_Request2/2.0.0RC1 ' .
|
||||
'(http://pear.php.net/package/http_request2) ' .
|
||||
'PHP/' . phpversion());
|
||||
$this->setHeader(
|
||||
'user-agent', 'HTTP_Request2/2.1.1 ' .
|
||||
'(http://pear.php.net/package/http_request2) PHP/' . phpversion()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,7 +247,8 @@ class HTTP_Request2 implements SplSubject
|
||||
* and converted to auth data. If the URL does not have a path component,
|
||||
* that will be set to '/'.
|
||||
*
|
||||
* @param string|Net_URL2 Request URL
|
||||
* @param string|Net_URL2 $url Request URL
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
@ -287,7 +293,8 @@ class HTTP_Request2 implements SplSubject
|
||||
/**
|
||||
* Sets the request method
|
||||
*
|
||||
* @param string
|
||||
* @param string $method one of the methods defined in RFC 2616
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException if the method name is invalid
|
||||
*/
|
||||
@ -331,11 +338,14 @@ class HTTP_Request2 implements SplSubject
|
||||
* <li> 'store_body' - Whether to store response body in response object.
|
||||
* Set to false if receiving a huge response and
|
||||
* using an Observer to save it (boolean)</li>
|
||||
* <li> 'proxy_type' - Proxy type, 'http' or 'socks5' (string)</li>
|
||||
* <li> 'proxy_host' - Proxy server host (string)</li>
|
||||
* <li> 'proxy_port' - Proxy server port (integer)</li>
|
||||
* <li> 'proxy_user' - Proxy auth username (string)</li>
|
||||
* <li> 'proxy_password' - Proxy auth password (string)</li>
|
||||
* <li> 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)</li>
|
||||
* <li> 'proxy' - Shorthand for proxy_* parameters, proxy given as URL,
|
||||
* e.g. 'socks5://localhost:1080/' (string)</li>
|
||||
* <li> 'ssl_verify_peer' - Whether to verify peer's SSL certificate (bool)</li>
|
||||
* <li> 'ssl_verify_host' - Whether to check that Common Name in SSL
|
||||
* certificate matches host name (bool)</li>
|
||||
@ -357,9 +367,10 @@ class HTTP_Request2 implements SplSubject
|
||||
* browsers) (boolean)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param string|array configuration parameter name or array
|
||||
* @param string|array $nameOrConfig configuration parameter name or array
|
||||
* ('parameter name' => 'parameter value')
|
||||
* @param mixed parameter value if $nameOrConfig is not an array
|
||||
* @param mixed $value parameter value if $nameOrConfig is not an array
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException If the parameter is unknown
|
||||
*/
|
||||
@ -370,6 +381,16 @@ class HTTP_Request2 implements SplSubject
|
||||
$this->setConfig($name, $value);
|
||||
}
|
||||
|
||||
} elseif ('proxy' == $nameOrConfig) {
|
||||
$url = new Net_URL2($value);
|
||||
$this->setConfig(array(
|
||||
'proxy_type' => $url->getScheme(),
|
||||
'proxy_host' => $url->getHost(),
|
||||
'proxy_port' => $url->getPort(),
|
||||
'proxy_user' => rawurldecode($url->getUser()),
|
||||
'proxy_password' => rawurldecode($url->getPassword())
|
||||
));
|
||||
|
||||
} else {
|
||||
if (!array_key_exists($nameOrConfig, $this->config)) {
|
||||
throw new HTTP_Request2_LogicException(
|
||||
@ -386,7 +407,8 @@ class HTTP_Request2 implements SplSubject
|
||||
/**
|
||||
* Returns the value(s) of the configuration parameter(s)
|
||||
*
|
||||
* @param string parameter name
|
||||
* @param string $name parameter name
|
||||
*
|
||||
* @return mixed value of $name parameter, array of all configuration
|
||||
* parameters if $name is not given
|
||||
* @throws HTTP_Request2_LogicException If the parameter is unknown
|
||||
@ -407,9 +429,10 @@ class HTTP_Request2 implements SplSubject
|
||||
/**
|
||||
* Sets the autentification data
|
||||
*
|
||||
* @param string user name
|
||||
* @param string password
|
||||
* @param string authentication scheme
|
||||
* @param string $user user name
|
||||
* @param string $password password
|
||||
* @param string $scheme authentication scheme
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
*/
|
||||
public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC)
|
||||
@ -458,12 +481,13 @@ class HTTP_Request2 implements SplSubject
|
||||
* $req->setHeader('FOO'); // removes 'Foo' header from request
|
||||
* </code>
|
||||
*
|
||||
* @param string|array header name, header string ('Header: value')
|
||||
* @param string|array $name header name, header string ('Header: value')
|
||||
* or an array of headers
|
||||
* @param string|array|null header value if $name is not an array,
|
||||
* @param string|array|null $value header value if $name is not an array,
|
||||
* header will be removed if value is null
|
||||
* @param bool whether to replace previous header with the
|
||||
* @param bool $replace whether to replace previous header with the
|
||||
* same name or append to its value
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
@ -534,8 +558,9 @@ class HTTP_Request2 implements SplSubject
|
||||
* parameters, 'expires' and 'secure' will be set to null and false,
|
||||
* respectively. If you need further control, use CookieJar's methods.
|
||||
*
|
||||
* @param string cookie name
|
||||
* @param string cookie value
|
||||
* @param string $name cookie name
|
||||
* @param string $value cookie value
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException
|
||||
* @see setCookieJar()
|
||||
@ -543,8 +568,9 @@ class HTTP_Request2 implements SplSubject
|
||||
public function addCookie($name, $value)
|
||||
{
|
||||
if (!empty($this->cookieJar)) {
|
||||
$this->cookieJar->store(array('name' => $name, 'value' => $value),
|
||||
$this->url);
|
||||
$this->cookieJar->store(
|
||||
array('name' => $name, 'value' => $value), $this->url
|
||||
);
|
||||
|
||||
} else {
|
||||
$cookie = $name . '=' . $value;
|
||||
@ -567,10 +593,12 @@ class HTTP_Request2 implements SplSubject
|
||||
* If you provide file pointer rather than file name, it should support
|
||||
* fstat() and rewind() operations.
|
||||
*
|
||||
* @param string|resource|HTTP_Request2_MultipartBody Either a string
|
||||
* with the body or filename containing body or pointer to
|
||||
* an open file or object with multipart body data
|
||||
* @param bool Whether first parameter is a filename
|
||||
* @param string|resource|HTTP_Request2_MultipartBody $body Either a
|
||||
* string with the body or filename containing body or
|
||||
* pointer to an open file or object with multipart body data
|
||||
* @param bool $isFilename Whether
|
||||
* first parameter is a filename
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
@ -601,8 +629,8 @@ class HTTP_Request2 implements SplSubject
|
||||
*/
|
||||
public function getBody()
|
||||
{
|
||||
if (self::METHOD_POST == $this->method &&
|
||||
(!empty($this->postParams) || !empty($this->uploads))
|
||||
if (self::METHOD_POST == $this->method
|
||||
&& (!empty($this->postParams) || !empty($this->uploads))
|
||||
) {
|
||||
if (0 === strpos($this->headers['content-type'], 'application/x-www-form-urlencoded')) {
|
||||
$body = http_build_query($this->postParams, '', '&');
|
||||
@ -634,17 +662,18 @@ class HTTP_Request2 implements SplSubject
|
||||
* If you provide file pointers rather than file names, they should support
|
||||
* fstat() and rewind() operations.
|
||||
*
|
||||
* @param string name of file-upload field
|
||||
* @param string|resource|array full name of local file, pointer to
|
||||
* open file or an array of files
|
||||
* @param string filename to send in the request
|
||||
* @param string content-type of file being uploaded
|
||||
* @param string $fieldName name of file-upload field
|
||||
* @param string|resource|array $filename full name of local file,
|
||||
* pointer to open file or an array of files
|
||||
* @param string $sendFilename filename to send in the request
|
||||
* @param string $contentType content-type of file being uploaded
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
public function addUpload($fieldName, $filename, $sendFilename = null,
|
||||
$contentType = null)
|
||||
{
|
||||
public function addUpload(
|
||||
$fieldName, $filename, $sendFilename = null, $contentType = null
|
||||
) {
|
||||
if (!is_array($filename)) {
|
||||
$fileData = $this->fopenWrapper($filename, empty($contentType));
|
||||
$this->uploads[$fieldName] = array(
|
||||
@ -671,8 +700,8 @@ class HTTP_Request2 implements SplSubject
|
||||
'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types
|
||||
);
|
||||
}
|
||||
if (empty($this->headers['content-type']) ||
|
||||
'application/x-www-form-urlencoded' == $this->headers['content-type']
|
||||
if (empty($this->headers['content-type'])
|
||||
|| 'application/x-www-form-urlencoded' == $this->headers['content-type']
|
||||
) {
|
||||
$this->setHeader('content-type', 'multipart/form-data');
|
||||
}
|
||||
@ -683,8 +712,9 @@ class HTTP_Request2 implements SplSubject
|
||||
/**
|
||||
* Adds POST parameter(s) to the request.
|
||||
*
|
||||
* @param string|array parameter name or array ('name' => 'value')
|
||||
* @param mixed parameter value (can be an array)
|
||||
* @param string|array $name parameter name or array ('name' => 'value')
|
||||
* @param mixed $value parameter value (can be an array)
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
*/
|
||||
public function addPostParameter($name, $value = null)
|
||||
@ -706,7 +736,7 @@ class HTTP_Request2 implements SplSubject
|
||||
/**
|
||||
* Attaches a new observer
|
||||
*
|
||||
* @param SplObserver
|
||||
* @param SplObserver $observer any object implementing SplObserver
|
||||
*/
|
||||
public function attach(SplObserver $observer)
|
||||
{
|
||||
@ -721,7 +751,7 @@ class HTTP_Request2 implements SplSubject
|
||||
/**
|
||||
* Detaches an existing observer
|
||||
*
|
||||
* @param SplObserver
|
||||
* @param SplObserver $observer any object implementing SplObserver
|
||||
*/
|
||||
public function detach(SplObserver $observer)
|
||||
{
|
||||
@ -749,8 +779,8 @@ class HTTP_Request2 implements SplSubject
|
||||
* Adapters should use this method to set the current state of the request
|
||||
* and notify the observers.
|
||||
*
|
||||
* @param string event name
|
||||
* @param mixed event data
|
||||
* @param string $name event name
|
||||
* @param mixed $data event data
|
||||
*/
|
||||
public function setLastEvent($name, $data = null)
|
||||
{
|
||||
@ -807,7 +837,8 @@ class HTTP_Request2 implements SplSubject
|
||||
* </code>
|
||||
* will work.
|
||||
*
|
||||
* @param string|HTTP_Request2_Adapter
|
||||
* @param string|HTTP_Request2_Adapter $adapter Adapter to use
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
@ -818,7 +849,9 @@ class HTTP_Request2 implements SplSubject
|
||||
if (false === strpos($adapter, '_')) {
|
||||
$adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter);
|
||||
}
|
||||
if (preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)) {
|
||||
if (!class_exists($adapter, false)
|
||||
&& preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)
|
||||
) {
|
||||
include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php';
|
||||
}
|
||||
if (!class_exists($adapter, false)) {
|
||||
@ -848,8 +881,11 @@ class HTTP_Request2 implements SplSubject
|
||||
* responses. Cookies from jar will be automatically added to the request
|
||||
* headers based on request URL.
|
||||
*
|
||||
* @param HTTP_Request2_CookieJar|bool Existing CookieJar object, true to
|
||||
* @param HTTP_Request2_CookieJar|bool $jar Existing CookieJar object, true to
|
||||
* create a new one, false to remove
|
||||
*
|
||||
* @return HTTP_Request2
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
public function setCookieJar($jar = true)
|
||||
{
|
||||
@ -899,7 +935,7 @@ class HTTP_Request2 implements SplSubject
|
||||
throw new HTTP_Request2_LogicException(
|
||||
'HTTP_Request2 needs an absolute HTTP(S) request URL, '
|
||||
. ($this->url instanceof Net_URL2
|
||||
? 'none' : "'" . $this->url->__toString() . "'")
|
||||
? "'" . $this->url->__toString() . "'" : 'none')
|
||||
. ' given',
|
||||
HTTP_Request2_Exception::INVALID_ARGUMENT
|
||||
);
|
||||
@ -916,7 +952,7 @@ class HTTP_Request2 implements SplSubject
|
||||
// strlen() and substr(); see bug #1781, bug #10605
|
||||
if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
|
||||
$oldEncoding = mb_internal_encoding();
|
||||
mb_internal_encoding('iso-8859-1');
|
||||
mb_internal_encoding('8bit');
|
||||
}
|
||||
|
||||
try {
|
||||
@ -940,9 +976,11 @@ class HTTP_Request2 implements SplSubject
|
||||
/**
|
||||
* Wrapper around fopen()/fstat() used by setBody() and addUpload()
|
||||
*
|
||||
* @param string|resource file name or pointer to open file
|
||||
* @param bool whether to try autodetecting MIME type of file,
|
||||
* will only work if $file is a filename, not pointer
|
||||
* @param string|resource $file file name or pointer to open file
|
||||
* @param bool $detectType whether to try autodetecting MIME
|
||||
* type of file, will only work if $file is a
|
||||
* filename, not pointer
|
||||
*
|
||||
* @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type)
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
@ -960,16 +998,12 @@ class HTTP_Request2 implements SplSubject
|
||||
'size' => 0
|
||||
);
|
||||
if (is_string($file)) {
|
||||
$track = @ini_set('track_errors', 1);
|
||||
if (!($fileData['fp'] = @fopen($file, 'rb'))) {
|
||||
$e = new HTTP_Request2_LogicException(
|
||||
$php_errormsg, HTTP_Request2_Exception::READ_ERROR
|
||||
$error = error_get_last();
|
||||
throw new HTTP_Request2_LogicException(
|
||||
$error['message'], HTTP_Request2_Exception::READ_ERROR
|
||||
);
|
||||
}
|
||||
@ini_set('track_errors', $track);
|
||||
if (isset($e)) {
|
||||
throw $e;
|
||||
}
|
||||
if ($detectType) {
|
||||
$fileData['type'] = self::detectMimeType($file);
|
||||
}
|
||||
@ -991,7 +1025,8 @@ class HTTP_Request2 implements SplSubject
|
||||
* deprecated mime_content_type() function in the other case. If neither
|
||||
* works, default 'application/octet-stream' MIME type is returned
|
||||
*
|
||||
* @param string filename
|
||||
* @param string $filename file name
|
||||
*
|
||||
* @return string file MIME type
|
||||
*/
|
||||
protected static function detectMimeType($filename)
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Adapter.php 308322 2011-02-14 13:58:03Z avb $
|
||||
* @version SVN: $Id: Adapter.php 324415 2012-03-21 10:50:50Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -56,7 +56,9 @@ require_once 'HTTP/Request2/Response.php';
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @version Release: 2.0.0RC1
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
abstract class HTTP_Request2_Adapter
|
||||
{
|
||||
@ -100,7 +102,8 @@ abstract class HTTP_Request2_Adapter
|
||||
/**
|
||||
* Sends request to the remote server and returns its response
|
||||
*
|
||||
* @param HTTP_Request2
|
||||
* @param HTTP_Request2 $request HTTP request message
|
||||
*
|
||||
* @return HTTP_Request2_Response
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
@ -109,9 +112,9 @@ abstract class HTTP_Request2_Adapter
|
||||
/**
|
||||
* Calculates length of the request body, adds proper headers
|
||||
*
|
||||
* @param array associative array of request headers, this method will
|
||||
* add proper 'Content-Length' and 'Content-Type' headers
|
||||
* to this array (or remove them if not needed)
|
||||
* @param array &$headers associative array of request headers, this method
|
||||
* will add proper 'Content-Length' and 'Content-Type'
|
||||
* headers to this array (or remove them if not needed)
|
||||
*/
|
||||
protected function calculateRequestLength(&$headers)
|
||||
{
|
||||
@ -130,8 +133,8 @@ abstract class HTTP_Request2_Adapter
|
||||
$this->requestBody->rewind();
|
||||
}
|
||||
|
||||
if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||
|
||||
0 == $this->contentLength
|
||||
if (in_array($this->request->getMethod(), self::$bodyDisallowed)
|
||||
|| 0 == $this->contentLength
|
||||
) {
|
||||
// No body: send a Content-Length header nonetheless (request #12900),
|
||||
// but do that only for methods that require a body (bug #14740)
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Curl.php 310800 2011-05-06 07:29:56Z avb $
|
||||
* @version SVN: $Id: Curl.php 324746 2012-04-03 15:09:16Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -52,7 +52,9 @@ require_once 'HTTP/Request2/Adapter.php';
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @version Release: 2.0.0RC1
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
{
|
||||
@ -153,7 +155,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Creates a subclass of HTTP_Request2_Exception from curl error data
|
||||
*
|
||||
* @param resource curl handle
|
||||
* @param resource $ch curl handle
|
||||
*
|
||||
* @return HTTP_Request2_Exception
|
||||
*/
|
||||
protected static function wrapCurlError($ch)
|
||||
@ -173,7 +176,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Sends request to the remote server and returns its response
|
||||
*
|
||||
* @param HTTP_Request2
|
||||
* @param HTTP_Request2 $request HTTP request message
|
||||
*
|
||||
* @return HTTP_Request2_Response
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
@ -315,8 +319,10 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port);
|
||||
if ($user = $this->request->getConfig('proxy_user')) {
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $user . ':' .
|
||||
$this->request->getConfig('proxy_password'));
|
||||
curl_setopt(
|
||||
$ch, CURLOPT_PROXYUSERPWD,
|
||||
$user . ':' . $this->request->getConfig('proxy_password')
|
||||
);
|
||||
switch ($this->request->getConfig('proxy_auth_scheme')) {
|
||||
case HTTP_Request2::AUTH_BASIC:
|
||||
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
||||
@ -325,6 +331,20 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
|
||||
}
|
||||
}
|
||||
if ($type = $this->request->getConfig('proxy_type')) {
|
||||
switch ($type) {
|
||||
case 'http':
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
||||
break;
|
||||
case 'socks5':
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
|
||||
break;
|
||||
default:
|
||||
throw new HTTP_Request2_NotImplementedException(
|
||||
"Proxy type '{$type}' is not supported"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set authentication data
|
||||
@ -391,8 +411,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
* and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large
|
||||
* file uploads, use Socket adapter instead.
|
||||
*
|
||||
* @param resource cURL handle
|
||||
* @param array Request headers
|
||||
* @param resource $ch cURL handle
|
||||
* @param array &$headers Request headers
|
||||
*/
|
||||
protected function workaroundPhpBug47204($ch, &$headers)
|
||||
{
|
||||
@ -403,8 +423,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
) {
|
||||
curl_setopt($ch, CURLOPT_READFUNCTION, array($this, 'callbackReadBody'));
|
||||
|
||||
// rewind may be needed, read the whole body into memory
|
||||
} else {
|
||||
// rewind may be needed, read the whole body into memory
|
||||
if ($this->requestBody instanceof HTTP_Request2_MultipartBody) {
|
||||
$this->requestBody = $this->requestBody->__toString();
|
||||
|
||||
@ -424,9 +444,10 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Callback function called by cURL for reading the request body
|
||||
*
|
||||
* @param resource cURL handle
|
||||
* @param resource file descriptor (not used)
|
||||
* @param integer maximum length of data to return
|
||||
* @param resource $ch cURL handle
|
||||
* @param resource $fd file descriptor (not used)
|
||||
* @param integer $length maximum length of data to return
|
||||
*
|
||||
* @return string part of the request body, up to $length bytes
|
||||
*/
|
||||
protected function callbackReadBody($ch, $fd, $length)
|
||||
@ -437,8 +458,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
);
|
||||
$this->eventSentHeaders = true;
|
||||
}
|
||||
if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||
|
||||
0 == $this->contentLength || $this->position >= $this->contentLength
|
||||
if (in_array($this->request->getMethod(), self::$bodyDisallowed)
|
||||
|| 0 == $this->contentLength || $this->position >= $this->contentLength
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
@ -457,8 +478,9 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Callback function called by cURL for saving the response headers
|
||||
*
|
||||
* @param resource cURL handle
|
||||
* @param string response header (with trailing CRLF)
|
||||
* @param resource $ch cURL handle
|
||||
* @param string $string response header (with trailing CRLF)
|
||||
*
|
||||
* @return integer number of bytes saved
|
||||
* @see HTTP_Request2_Response::parseHeaderLine()
|
||||
*/
|
||||
@ -467,8 +489,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
// we may receive a second set of headers if doing e.g. digest auth
|
||||
if ($this->eventReceivedHeaders || !$this->eventSentHeaders) {
|
||||
// don't bother with 100-Continue responses (bug #15785)
|
||||
if (!$this->eventSentHeaders ||
|
||||
$this->response->getStatus() >= 200
|
||||
if (!$this->eventSentHeaders
|
||||
|| $this->response->getStatus() >= 200
|
||||
) {
|
||||
$this->request->setLastEvent(
|
||||
'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
|
||||
@ -535,9 +557,11 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Callback function called by cURL for saving the response body
|
||||
*
|
||||
* @param resource cURL handle (not used)
|
||||
* @param string part of the response body
|
||||
* @param resource $ch cURL handle (not used)
|
||||
* @param string $string part of the response body
|
||||
*
|
||||
* @return integer number of bytes saved
|
||||
* @throws HTTP_Request2_MessageException
|
||||
* @see HTTP_Request2_Response::appendBody()
|
||||
*/
|
||||
protected function callbackWriteBody($ch, $string)
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Mock.php 308322 2011-02-14 13:58:03Z avb $
|
||||
* @version SVN: $Id: Mock.php 324937 2012-04-07 10:05:57Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -66,7 +66,9 @@ require_once 'HTTP/Request2/Adapter.php';
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @version Release: 2.0.0RC1
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
|
||||
{
|
||||
@ -79,19 +81,33 @@ class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Returns the next response from the queue built by addResponse()
|
||||
*
|
||||
* If the queue is empty it will return default empty response with status 400,
|
||||
* Only responses without explicit URLs or with URLs equal to request URL
|
||||
* will be considered. If matching response is not found or the queue is
|
||||
* empty then default empty response with status 400 will be returned,
|
||||
* if an Exception object was added to the queue it will be thrown.
|
||||
*
|
||||
* @param HTTP_Request2
|
||||
* @param HTTP_Request2 $request HTTP request message
|
||||
*
|
||||
* @return HTTP_Request2_Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendRequest(HTTP_Request2 $request)
|
||||
{
|
||||
if (count($this->responses) > 0) {
|
||||
$response = array_shift($this->responses);
|
||||
if ($response instanceof HTTP_Request2_Response) {
|
||||
$requestUrl = (string)$request->getUrl();
|
||||
$response = null;
|
||||
foreach ($this->responses as $k => $v) {
|
||||
if (!$v[1] || $requestUrl == $v[1]) {
|
||||
$response = $v[0];
|
||||
array_splice($this->responses, $k, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$response) {
|
||||
return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n");
|
||||
|
||||
} elseif ($response instanceof HTTP_Request2_Response) {
|
||||
return $response;
|
||||
|
||||
} else {
|
||||
// rethrow the exception
|
||||
$class = get_class($response);
|
||||
@ -99,19 +115,19 @@ class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
|
||||
$code = $response->getCode();
|
||||
throw new $class($message, $code);
|
||||
}
|
||||
} else {
|
||||
return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds response to the queue
|
||||
*
|
||||
* @param mixed either a string, a pointer to an open file,
|
||||
* @param mixed $response either a string, a pointer to an open file,
|
||||
* an instance of HTTP_Request2_Response or Exception
|
||||
* @param string $url A request URL this response should be valid for
|
||||
* (see {@link http://pear.php.net/bugs/bug.php?id=19276})
|
||||
*
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
public function addResponse($response)
|
||||
public function addResponse($response, $url = null)
|
||||
{
|
||||
if (is_string($response)) {
|
||||
$response = self::createResponseFromString($response);
|
||||
@ -122,13 +138,14 @@ class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
|
||||
) {
|
||||
throw new HTTP_Request2_Exception('Parameter is not a valid response');
|
||||
}
|
||||
$this->responses[] = $response;
|
||||
$this->responses[] = array($response, $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP_Request2_Response object from a string
|
||||
*
|
||||
* @param string
|
||||
* @param string $str string containing HTTP response message
|
||||
*
|
||||
* @return HTTP_Request2_Response
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
@ -150,7 +167,8 @@ class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Creates a new HTTP_Request2_Response object from a file
|
||||
*
|
||||
* @param resource file pointer returned by fopen()
|
||||
* @param resource $fp file pointer returned by fopen()
|
||||
*
|
||||
* @return HTTP_Request2_Response
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,15 +37,16 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Socket.php 309921 2011-04-03 16:43:02Z avb $
|
||||
* @version SVN: $Id: Socket.php 324953 2012-04-08 07:24:12Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for HTTP_Request2 adapters
|
||||
*/
|
||||
/** Base class for HTTP_Request2 adapters */
|
||||
require_once 'HTTP/Request2/Adapter.php';
|
||||
|
||||
/** Socket wrapper class */
|
||||
require_once 'HTTP/Request2/SocketWrapper.php';
|
||||
|
||||
/**
|
||||
* Socket-based adapter for HTTP_Request2
|
||||
*
|
||||
@ -55,7 +56,9 @@ require_once 'HTTP/Request2/Adapter.php';
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @version Release: 2.0.0RC1
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
{
|
||||
@ -92,7 +95,7 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
|
||||
/**
|
||||
* Connected socket
|
||||
* @var resource
|
||||
* @var HTTP_Request2_SocketWrapper
|
||||
* @see connect()
|
||||
*/
|
||||
protected $socket;
|
||||
@ -109,12 +112,6 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
*/
|
||||
protected $proxyChallenge;
|
||||
|
||||
/**
|
||||
* Sum of start time and global timeout, exception will be thrown if request continues past this time
|
||||
* @var integer
|
||||
*/
|
||||
protected $deadline = null;
|
||||
|
||||
/**
|
||||
* Remaining length of the current chunk, when reading chunked response
|
||||
* @var integer
|
||||
@ -135,7 +132,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Sends request to the remote server and returns its response
|
||||
*
|
||||
* @param HTTP_Request2
|
||||
* @param HTTP_Request2 $request HTTP request message
|
||||
*
|
||||
* @return HTTP_Request2_Response
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
@ -143,31 +141,14 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
{
|
||||
$this->request = $request;
|
||||
|
||||
// Use global request timeout if given, see feature requests #5735, #8964
|
||||
if ($timeout = $request->getConfig('timeout')) {
|
||||
$this->deadline = time() + $timeout;
|
||||
} else {
|
||||
$this->deadline = null;
|
||||
}
|
||||
|
||||
try {
|
||||
$keepAlive = $this->connect();
|
||||
$headers = $this->prepareHeaders();
|
||||
if (false === @fwrite($this->socket, $headers, strlen($headers))) {
|
||||
throw new HTTP_Request2_MessageException('Error writing request');
|
||||
}
|
||||
$this->socket->write($headers);
|
||||
// provide request headers to the observer, see request #7633
|
||||
$this->request->setLastEvent('sentHeaders', $headers);
|
||||
$this->writeBody();
|
||||
|
||||
if ($this->deadline && time() > $this->deadline) {
|
||||
throw new HTTP_Request2_MessageException(
|
||||
'Request timed out after ' .
|
||||
$request->getConfig('timeout') . ' second(s)',
|
||||
HTTP_Request2_Exception::TIMEOUT
|
||||
);
|
||||
}
|
||||
|
||||
$response = $this->readResponse();
|
||||
|
||||
if ($jar = $request->getCookieJar()) {
|
||||
@ -226,21 +207,29 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$reqPort = $secure? 443: 80;
|
||||
}
|
||||
|
||||
if ($host = $this->request->getConfig('proxy_host')) {
|
||||
$httpProxy = $socksProxy = false;
|
||||
if (!($host = $this->request->getConfig('proxy_host'))) {
|
||||
$host = $reqHost;
|
||||
$port = $reqPort;
|
||||
} else {
|
||||
if (!($port = $this->request->getConfig('proxy_port'))) {
|
||||
throw new HTTP_Request2_LogicException(
|
||||
'Proxy port not provided',
|
||||
HTTP_Request2_Exception::MISSING_VALUE
|
||||
);
|
||||
}
|
||||
$proxy = true;
|
||||
if ('http' == ($type = $this->request->getConfig('proxy_type'))) {
|
||||
$httpProxy = true;
|
||||
} elseif ('socks5' == $type) {
|
||||
$socksProxy = true;
|
||||
} else {
|
||||
$host = $reqHost;
|
||||
$port = $reqPort;
|
||||
$proxy = false;
|
||||
throw new HTTP_Request2_NotImplementedException(
|
||||
"Proxy type '{$type}' is not supported"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($tunnel && !$proxy) {
|
||||
if ($tunnel && !$httpProxy) {
|
||||
throw new HTTP_Request2_LogicException(
|
||||
"Trying to perform CONNECT request without proxy",
|
||||
HTTP_Request2_Exception::MISSING_VALUE
|
||||
@ -255,8 +244,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
|
||||
// RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
|
||||
// connection token to a proxy server...
|
||||
if ($proxy && !$secure &&
|
||||
!empty($headers['connection']) && 'Keep-Alive' == $headers['connection']
|
||||
if ($httpProxy && !$secure && !empty($headers['connection'])
|
||||
&& 'Keep-Alive' == $headers['connection']
|
||||
) {
|
||||
$this->request->setHeader('connection');
|
||||
}
|
||||
@ -265,7 +254,6 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
empty($headers['connection'])) ||
|
||||
(!empty($headers['connection']) &&
|
||||
'Keep-Alive' == $headers['connection']);
|
||||
$host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host;
|
||||
|
||||
$options = array();
|
||||
if ($secure || $tunnel) {
|
||||
@ -283,56 +271,62 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
ksort($options);
|
||||
}
|
||||
|
||||
// Use global request timeout if given, see feature requests #5735, #8964
|
||||
if ($timeout = $this->request->getConfig('timeout')) {
|
||||
$deadline = time() + $timeout;
|
||||
} else {
|
||||
$deadline = null;
|
||||
}
|
||||
|
||||
// Changing SSL context options after connection is established does *not*
|
||||
// work, we need a new connection if options change
|
||||
$remote = $host . ':' . $port;
|
||||
$socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') .
|
||||
(empty($options)? '': ':' . serialize($options));
|
||||
$remote = ((!$secure || $httpProxy || $socksProxy)? 'tcp://': 'ssl://')
|
||||
. $host . ':' . $port;
|
||||
$socketKey = $remote . (
|
||||
($secure && $httpProxy || $socksProxy)
|
||||
? "->{$reqHost}:{$reqPort}" : ''
|
||||
) . (empty($options)? '': ':' . serialize($options));
|
||||
unset($this->socket);
|
||||
|
||||
// We use persistent connections and have a connected socket?
|
||||
// Ensure that the socket is still connected, see bug #16149
|
||||
if ($keepAlive && !empty(self::$sockets[$socketKey]) &&
|
||||
!feof(self::$sockets[$socketKey])
|
||||
if ($keepAlive && !empty(self::$sockets[$socketKey])
|
||||
&& !self::$sockets[$socketKey]->eof()
|
||||
) {
|
||||
$this->socket =& self::$sockets[$socketKey];
|
||||
|
||||
} elseif ($secure && $proxy && !$tunnel) {
|
||||
$this->establishTunnel();
|
||||
$this->request->setLastEvent(
|
||||
'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}"
|
||||
} else {
|
||||
if ($socksProxy) {
|
||||
require_once 'HTTP/Request2/SOCKS5.php';
|
||||
|
||||
$this->socket = new HTTP_Request2_SOCKS5(
|
||||
$remote, $this->request->getConfig('connect_timeout'),
|
||||
$options, $this->request->getConfig('proxy_user'),
|
||||
$this->request->getConfig('proxy_password')
|
||||
);
|
||||
self::$sockets[$socketKey] =& $this->socket;
|
||||
// handle request timeouts ASAP
|
||||
$this->socket->setDeadline($deadline, $this->request->getConfig('timeout'));
|
||||
$this->socket->connect($reqHost, $reqPort);
|
||||
if (!$secure) {
|
||||
$conninfo = "tcp://{$reqHost}:{$reqPort} via {$remote}";
|
||||
} else {
|
||||
$this->socket->enableCrypto();
|
||||
$conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}";
|
||||
}
|
||||
|
||||
} elseif ($secure && $httpProxy && !$tunnel) {
|
||||
$this->establishTunnel();
|
||||
$conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}";
|
||||
|
||||
} else {
|
||||
// Set SSL context options if doing HTTPS request or creating a tunnel
|
||||
$context = stream_context_create();
|
||||
foreach ($options as $name => $value) {
|
||||
if (!stream_context_set_option($context, 'ssl', $name, $value)) {
|
||||
throw new HTTP_Request2_LogicException(
|
||||
"Error setting SSL context option '{$name}'"
|
||||
$this->socket = new HTTP_Request2_SocketWrapper(
|
||||
$remote, $this->request->getConfig('connect_timeout'), $options
|
||||
);
|
||||
}
|
||||
}
|
||||
$track = @ini_set('track_errors', 1);
|
||||
$this->socket = @stream_socket_client(
|
||||
$remote, $errno, $errstr,
|
||||
$this->request->getConfig('connect_timeout'),
|
||||
STREAM_CLIENT_CONNECT, $context
|
||||
);
|
||||
if (!$this->socket) {
|
||||
$e = new HTTP_Request2_ConnectionException(
|
||||
"Unable to connect to {$remote}. Error: "
|
||||
. (empty($errstr)? $php_errormsg: $errstr), 0, $errno
|
||||
);
|
||||
}
|
||||
@ini_set('track_errors', $track);
|
||||
if (isset($e)) {
|
||||
throw $e;
|
||||
}
|
||||
$this->request->setLastEvent('connect', $remote);
|
||||
$this->request->setLastEvent('connect', empty($conninfo)? $remote: $conninfo);
|
||||
self::$sockets[$socketKey] =& $this->socket;
|
||||
}
|
||||
$this->socket->setDeadline($deadline, $this->request->getConfig('timeout'));
|
||||
return $keepAlive;
|
||||
}
|
||||
|
||||
@ -351,8 +345,7 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$donor = new self;
|
||||
$connect = new HTTP_Request2(
|
||||
$this->request->getUrl(), HTTP_Request2::METHOD_CONNECT,
|
||||
array_merge($this->request->getConfig(),
|
||||
array('adapter' => $donor))
|
||||
array_merge($this->request->getConfig(), array('adapter' => $donor))
|
||||
);
|
||||
$response = $connect->send();
|
||||
// Need any successful (2XX) response
|
||||
@ -363,37 +356,23 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
);
|
||||
}
|
||||
$this->socket = $donor->socket;
|
||||
|
||||
$modes = array(
|
||||
STREAM_CRYPTO_METHOD_TLS_CLIENT,
|
||||
STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
|
||||
STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
|
||||
STREAM_CRYPTO_METHOD_SSLv2_CLIENT
|
||||
);
|
||||
|
||||
foreach ($modes as $mode) {
|
||||
if (stream_socket_enable_crypto($this->socket, true, $mode)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new HTTP_Request2_ConnectionException(
|
||||
'Failed to enable secure connection when connecting through proxy'
|
||||
);
|
||||
$this->socket->enableCrypto();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether current connection may be reused or should be closed
|
||||
*
|
||||
* @param boolean whether connection could be persistent
|
||||
* in the first place
|
||||
* @param HTTP_Request2_Response response object to check
|
||||
* @param boolean $requestKeepAlive whether connection could
|
||||
* be persistent in the first place
|
||||
* @param HTTP_Request2_Response $response response object to check
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response)
|
||||
{
|
||||
// Do not close socket on successful CONNECT request
|
||||
if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() &&
|
||||
200 <= $response->getStatus() && 300 > $response->getStatus()
|
||||
if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod()
|
||||
&& 200 <= $response->getStatus() && 300 > $response->getStatus()
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@ -414,8 +393,7 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
*/
|
||||
protected function disconnect()
|
||||
{
|
||||
if (is_resource($this->socket)) {
|
||||
fclose($this->socket);
|
||||
if (!empty($this->socket)) {
|
||||
$this->socket = null;
|
||||
$this->request->setLastEvent('disconnect');
|
||||
}
|
||||
@ -428,21 +406,22 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
* is attempted, also if number of redirects performed already is equal to
|
||||
* 'max_redirects' configuration parameter.
|
||||
*
|
||||
* @param HTTP_Request2 Original request
|
||||
* @param HTTP_Request2_Response Response containing redirect
|
||||
* @param HTTP_Request2 $request Original request
|
||||
* @param HTTP_Request2_Response $response Response containing redirect
|
||||
*
|
||||
* @return HTTP_Request2_Response Response from a new location
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
protected function handleRedirect(HTTP_Request2 $request,
|
||||
HTTP_Request2_Response $response)
|
||||
{
|
||||
protected function handleRedirect(
|
||||
HTTP_Request2 $request, HTTP_Request2_Response $response
|
||||
) {
|
||||
if (is_null($this->redirectCountdown)) {
|
||||
$this->redirectCountdown = $request->getConfig('max_redirects');
|
||||
}
|
||||
if (0 == $this->redirectCountdown) {
|
||||
$this->redirectCountdown = null;
|
||||
// Copying cURL behaviour
|
||||
throw new HTTP_Request2_MessageException (
|
||||
throw new HTTP_Request2_MessageException(
|
||||
'Maximum (' . $request->getConfig('max_redirects') . ') redirects followed',
|
||||
HTTP_Request2_Exception::TOO_MANY_REDIRECTS
|
||||
);
|
||||
@ -468,7 +447,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
}
|
||||
$redirect = clone $request;
|
||||
$redirect->setUrl($redirectUrl);
|
||||
if (303 == $response->getStatus() || (!$request->getConfig('strict_redirects')
|
||||
if (303 == $response->getStatus()
|
||||
|| (!$request->getConfig('strict_redirects')
|
||||
&& in_array($response->getStatus(), array(301, 302)))
|
||||
) {
|
||||
$redirect->setMethod(HTTP_Request2::METHOD_GET);
|
||||
@ -494,7 +474,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
*
|
||||
* The method stores challenge values in $challenges static property
|
||||
*
|
||||
* @param HTTP_Request2_Response response to check
|
||||
* @param HTTP_Request2_Response $response response to check
|
||||
*
|
||||
* @return boolean whether another request should be performed
|
||||
* @throws HTTP_Request2_Exception in case of unsupported challenge parameters
|
||||
*/
|
||||
@ -512,8 +493,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$scheme = $url->getScheme();
|
||||
$host = $scheme . '://' . $url->getHost();
|
||||
if ($port = $url->getPort()) {
|
||||
if ((0 == strcasecmp($scheme, 'http') && 80 != $port) ||
|
||||
(0 == strcasecmp($scheme, 'https') && 443 != $port)
|
||||
if ((0 == strcasecmp($scheme, 'http') && 80 != $port)
|
||||
|| (0 == strcasecmp($scheme, 'https') && 443 != $port)
|
||||
) {
|
||||
$host .= ':' . $port;
|
||||
}
|
||||
@ -534,8 +515,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
|
||||
$ret = true;
|
||||
foreach ($prefixes as $prefix) {
|
||||
if (!empty(self::$challenges[$prefix]) &&
|
||||
(empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))
|
||||
if (!empty(self::$challenges[$prefix])
|
||||
&& (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))
|
||||
) {
|
||||
// probably credentials are invalid
|
||||
$ret = false;
|
||||
@ -558,7 +539,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
*
|
||||
* The method stores challenge values in $challenges static property
|
||||
*
|
||||
* @param HTTP_Request2_Response response to check
|
||||
* @param HTTP_Request2_Response $response response to check
|
||||
*
|
||||
* @return boolean whether another request should be performed
|
||||
* @throws HTTP_Request2_Exception in case of unsupported challenge parameters
|
||||
*/
|
||||
@ -574,8 +556,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$key = 'proxy://' . $this->request->getConfig('proxy_host') .
|
||||
':' . $this->request->getConfig('proxy_port');
|
||||
|
||||
if (!empty(self::$challenges[$key]) &&
|
||||
(empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))
|
||||
if (!empty(self::$challenges[$key])
|
||||
&& (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))
|
||||
) {
|
||||
$ret = false;
|
||||
} else {
|
||||
@ -608,7 +590,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
* quoted-string handling, unfortunately that means failure to authorize
|
||||
* sometimes
|
||||
*
|
||||
* @param string value of WWW-Authenticate or Proxy-Authenticate header
|
||||
* @param string $headerValue value of WWW-Authenticate or Proxy-Authenticate header
|
||||
*
|
||||
* @return mixed associative array with challenge parameters, false if
|
||||
* no challenge is present in header value
|
||||
* @throws HTTP_Request2_NotImplementedException in case of unsupported challenge parameters
|
||||
@ -637,8 +620,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
}
|
||||
}
|
||||
// we only support qop=auth
|
||||
if (!empty($paramsAry['qop']) &&
|
||||
!in_array('auth', array_map('trim', explode(',', $paramsAry['qop'])))
|
||||
if (!empty($paramsAry['qop'])
|
||||
&& !in_array('auth', array_map('trim', explode(',', $paramsAry['qop'])))
|
||||
) {
|
||||
throw new HTTP_Request2_NotImplementedException(
|
||||
"Only 'auth' qop is currently supported in digest authentication, " .
|
||||
@ -659,8 +642,9 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Parses [Proxy-]Authentication-Info header value and updates challenge
|
||||
*
|
||||
* @param array challenge to update
|
||||
* @param string value of [Proxy-]Authentication-Info header
|
||||
* @param array &$challenge challenge to update
|
||||
* @param string $headerValue value of [Proxy-]Authentication-Info header
|
||||
*
|
||||
* @todo validate server rspauth response
|
||||
*/
|
||||
protected function updateChallenge(&$challenge, $headerValue)
|
||||
@ -687,17 +671,18 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Creates a value for [Proxy-]Authorization header when using digest authentication
|
||||
*
|
||||
* @param string user name
|
||||
* @param string password
|
||||
* @param string request URL
|
||||
* @param array digest challenge parameters
|
||||
* @param string $user user name
|
||||
* @param string $password password
|
||||
* @param string $url request URL
|
||||
* @param array &$challenge digest challenge parameters
|
||||
*
|
||||
* @return string value of [Proxy-]Authorization request header
|
||||
* @link http://tools.ietf.org/html/rfc2617#section-3.2.2
|
||||
*/
|
||||
protected function createDigestResponse($user, $password, $url, &$challenge)
|
||||
{
|
||||
if (false !== ($q = strpos($url, '?')) &&
|
||||
$this->request->getConfig('digest_compat_ie')
|
||||
if (false !== ($q = strpos($url, '?'))
|
||||
&& $this->request->getConfig('digest_compat_ie')
|
||||
) {
|
||||
$url = substr($url, 0, $q);
|
||||
}
|
||||
@ -713,8 +698,10 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$challenge['nc'] = 1;
|
||||
}
|
||||
$nc = sprintf('%08x', $challenge['nc']++);
|
||||
$digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' .
|
||||
$challenge['cnonce'] . ':auth:' . $a2);
|
||||
$digest = md5(
|
||||
$a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' .
|
||||
$challenge['cnonce'] . ':auth:' . $a2
|
||||
);
|
||||
}
|
||||
return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' .
|
||||
'realm="' . $challenge['realm'] . '", ' .
|
||||
@ -732,9 +719,10 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Adds 'Authorization' header (if needed) to request headers array
|
||||
*
|
||||
* @param array request headers
|
||||
* @param string request host (needed for digest authentication)
|
||||
* @param string request URL (needed for digest authentication)
|
||||
* @param array &$headers request headers
|
||||
* @param string $requestHost request host (needed for digest authentication)
|
||||
* @param string $requestUrl request URL (needed for digest authentication)
|
||||
*
|
||||
* @throws HTTP_Request2_NotImplementedException
|
||||
*/
|
||||
protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl)
|
||||
@ -744,8 +732,9 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
}
|
||||
switch ($auth['scheme']) {
|
||||
case HTTP_Request2::AUTH_BASIC:
|
||||
$headers['authorization'] =
|
||||
'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']);
|
||||
$headers['authorization'] = 'Basic ' . base64_encode(
|
||||
$auth['user'] . ':' . $auth['password']
|
||||
);
|
||||
break;
|
||||
|
||||
case HTTP_Request2::AUTH_DIGEST:
|
||||
@ -776,16 +765,17 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
/**
|
||||
* Adds 'Proxy-Authorization' header (if needed) to request headers array
|
||||
*
|
||||
* @param array request headers
|
||||
* @param string request URL (needed for digest authentication)
|
||||
* @param array &$headers request headers
|
||||
* @param string $requestUrl request URL (needed for digest authentication)
|
||||
*
|
||||
* @throws HTTP_Request2_NotImplementedException
|
||||
*/
|
||||
protected function addProxyAuthorizationHeader(&$headers, $requestUrl)
|
||||
{
|
||||
if (!$this->request->getConfig('proxy_host') ||
|
||||
!($user = $this->request->getConfig('proxy_user')) ||
|
||||
(0 == strcasecmp('https', $this->request->getUrl()->getScheme()) &&
|
||||
HTTP_Request2::METHOD_CONNECT != $this->request->getMethod())
|
||||
if (!$this->request->getConfig('proxy_host')
|
||||
|| !($user = $this->request->getConfig('proxy_user'))
|
||||
|| (0 == strcasecmp('https', $this->request->getUrl()->getScheme())
|
||||
&& HTTP_Request2::METHOD_CONNECT != $this->request->getMethod())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -793,8 +783,9 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$password = $this->request->getConfig('proxy_password');
|
||||
switch ($this->request->getConfig('proxy_auth_scheme')) {
|
||||
case HTTP_Request2::AUTH_BASIC:
|
||||
$headers['proxy-authorization'] =
|
||||
'Basic ' . base64_encode($user . ':' . $password);
|
||||
$headers['proxy-authorization'] = 'Basic ' . base64_encode(
|
||||
$user . ':' . $password
|
||||
);
|
||||
break;
|
||||
|
||||
case HTTP_Request2::AUTH_DIGEST:
|
||||
@ -845,8 +836,9 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$requestUrl = $host;
|
||||
|
||||
} else {
|
||||
if (!$this->request->getConfig('proxy_host') ||
|
||||
0 == strcasecmp($url->getScheme(), 'https')
|
||||
if (!$this->request->getConfig('proxy_host')
|
||||
|| 'http' != $this->request->getConfig('proxy_type')
|
||||
|| 0 == strcasecmp($url->getScheme(), 'https')
|
||||
) {
|
||||
$requestUrl = '';
|
||||
} else {
|
||||
@ -857,8 +849,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query);
|
||||
}
|
||||
|
||||
if ('1.1' == $this->request->getConfig('protocol_version') &&
|
||||
extension_loaded('zlib') && !isset($headers['accept-encoding'])
|
||||
if ('1.1' == $this->request->getConfig('protocol_version')
|
||||
&& extension_loaded('zlib') && !isset($headers['accept-encoding'])
|
||||
) {
|
||||
$headers['accept-encoding'] = 'gzip, deflate';
|
||||
}
|
||||
@ -888,8 +880,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
*/
|
||||
protected function writeBody()
|
||||
{
|
||||
if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||
|
||||
0 == $this->contentLength
|
||||
if (in_array($this->request->getMethod(), self::$bodyDisallowed)
|
||||
|| 0 == $this->contentLength
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -904,9 +896,7 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
} else {
|
||||
$str = $this->requestBody->read($bufferSize);
|
||||
}
|
||||
if (false === @fwrite($this->socket, $str, strlen($str))) {
|
||||
throw new HTTP_Request2_MessageException('Error writing request');
|
||||
}
|
||||
$this->socket->write($str);
|
||||
// Provide the length of written string to the observer, request #7630
|
||||
$this->request->setLastEvent('sentBodyPart', strlen($str));
|
||||
$position += strlen($str);
|
||||
@ -926,10 +916,10 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
|
||||
do {
|
||||
$response = new HTTP_Request2_Response(
|
||||
$this->readLine($bufferSize), true, $this->request->getUrl()
|
||||
$this->socket->readLine($bufferSize), true, $this->request->getUrl()
|
||||
);
|
||||
do {
|
||||
$headerLine = $this->readLine($bufferSize);
|
||||
$headerLine = $this->socket->readLine($bufferSize);
|
||||
$response->parseHeaderLine($headerLine);
|
||||
} while ('' != $headerLine);
|
||||
} while (in_array($response->getStatus(), array(100, 101)));
|
||||
@ -937,10 +927,10 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$this->request->setLastEvent('receivedHeaders', $response);
|
||||
|
||||
// No body possible in such responses
|
||||
if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() ||
|
||||
(HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() &&
|
||||
200 <= $response->getStatus() && 300 > $response->getStatus()) ||
|
||||
in_array($response->getStatus(), array(204, 304))
|
||||
if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod()
|
||||
|| (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod()
|
||||
&& 200 <= $response->getStatus() && 300 > $response->getStatus())
|
||||
|| in_array($response->getStatus(), array(204, 304))
|
||||
) {
|
||||
return $response;
|
||||
}
|
||||
@ -956,16 +946,16 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$toRead = ($chunked || null === $length)? null: $length;
|
||||
$this->chunkLength = 0;
|
||||
|
||||
while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) {
|
||||
while (!$this->socket->eof() && (is_null($toRead) || 0 < $toRead)) {
|
||||
if ($chunked) {
|
||||
$data = $this->readChunked($bufferSize);
|
||||
} elseif (is_null($toRead)) {
|
||||
$data = $this->fread($bufferSize);
|
||||
$data = $this->socket->read($bufferSize);
|
||||
} else {
|
||||
$data = $this->fread(min($toRead, $bufferSize));
|
||||
$data = $this->socket->read(min($toRead, $bufferSize));
|
||||
$toRead -= strlen($data);
|
||||
}
|
||||
if ('' == $data && (!$this->chunkLength || feof($this->socket))) {
|
||||
if ('' == $data && (!$this->chunkLength || $this->socket->eof())) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -987,69 +977,11 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads until either the end of the socket or a newline, whichever comes first
|
||||
*
|
||||
* Strips the trailing newline from the returned data, handles global
|
||||
* request timeout. Method idea borrowed from Net_Socket PEAR package.
|
||||
*
|
||||
* @param int buffer size to use for reading
|
||||
* @return Available data up to the newline (not including newline)
|
||||
* @throws HTTP_Request2_MessageException In case of timeout
|
||||
*/
|
||||
protected function readLine($bufferSize)
|
||||
{
|
||||
$line = '';
|
||||
while (!feof($this->socket)) {
|
||||
if ($this->deadline) {
|
||||
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
|
||||
}
|
||||
$line .= @fgets($this->socket, $bufferSize);
|
||||
$info = stream_get_meta_data($this->socket);
|
||||
if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {
|
||||
$reason = $this->deadline
|
||||
? 'after ' . $this->request->getConfig('timeout') . ' second(s)'
|
||||
: 'due to default_socket_timeout php.ini setting';
|
||||
throw new HTTP_Request2_MessageException(
|
||||
"Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT
|
||||
);
|
||||
}
|
||||
if (substr($line, -1) == "\n") {
|
||||
return rtrim($line, "\r\n");
|
||||
}
|
||||
}
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around fread(), handles global request timeout
|
||||
*
|
||||
* @param int Reads up to this number of bytes
|
||||
* @return Data read from socket
|
||||
* @throws HTTP_Request2_MessageException In case of timeout
|
||||
*/
|
||||
protected function fread($length)
|
||||
{
|
||||
if ($this->deadline) {
|
||||
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
|
||||
}
|
||||
$data = fread($this->socket, $length);
|
||||
$info = stream_get_meta_data($this->socket);
|
||||
if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {
|
||||
$reason = $this->deadline
|
||||
? 'after ' . $this->request->getConfig('timeout') . ' second(s)'
|
||||
: 'due to default_socket_timeout php.ini setting';
|
||||
throw new HTTP_Request2_MessageException(
|
||||
"Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a part of response body encoded with chunked Transfer-Encoding
|
||||
*
|
||||
* @param int buffer size to use for reading
|
||||
* @param int $bufferSize buffer size to use for reading
|
||||
*
|
||||
* @return string
|
||||
* @throws HTTP_Request2_MessageException
|
||||
*/
|
||||
@ -1057,7 +989,7 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
{
|
||||
// at start of the next chunk?
|
||||
if (0 == $this->chunkLength) {
|
||||
$line = $this->readLine($bufferSize);
|
||||
$line = $this->socket->readLine($bufferSize);
|
||||
if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
|
||||
throw new HTTP_Request2_MessageException(
|
||||
"Cannot decode chunked response, invalid chunk length '{$line}'",
|
||||
@ -1067,15 +999,15 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
|
||||
$this->chunkLength = hexdec($matches[1]);
|
||||
// Chunk with zero length indicates the end
|
||||
if (0 == $this->chunkLength) {
|
||||
$this->readLine($bufferSize);
|
||||
$this->socket->readLine($bufferSize);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
$data = $this->fread(min($this->chunkLength, $bufferSize));
|
||||
$data = $this->socket->read(min($this->chunkLength, $bufferSize));
|
||||
$this->chunkLength -= strlen($data);
|
||||
if (0 == $this->chunkLength) {
|
||||
$this->readLine($bufferSize); // Trailing CRLF
|
||||
$this->socket->readLine($bufferSize); // Trailing CRLF
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: CookieJar.php 308629 2011-02-24 17:34:24Z avb $
|
||||
* @version SVN: $Id: CookieJar.php 324415 2012-03-21 10:50:50Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -50,7 +50,9 @@ require_once 'HTTP/Request2.php';
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_CookieJar implements Serializable
|
||||
{
|
||||
@ -92,11 +94,14 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
/**
|
||||
* Class constructor, sets various options
|
||||
*
|
||||
* @param bool Controls serializing session cookies, see {@link serializeSessionCookies()}
|
||||
* @param bool Controls using Public Suffix List, see {@link usePublicSuffixList()}
|
||||
* @param bool $serializeSessionCookies Controls serializing session cookies,
|
||||
* see {@link serializeSessionCookies()}
|
||||
* @param bool $usePublicSuffixList Controls using Public Suffix List,
|
||||
* see {@link usePublicSuffixList()}
|
||||
*/
|
||||
public function __construct($serializeSessionCookies = false, $usePublicSuffixList = true)
|
||||
{
|
||||
public function __construct(
|
||||
$serializeSessionCookies = false, $usePublicSuffixList = true
|
||||
) {
|
||||
$this->serializeSessionCookies($serializeSessionCookies);
|
||||
$this->usePublicSuffixList($usePublicSuffixList);
|
||||
}
|
||||
@ -129,8 +134,10 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
* 'expires' field will be converted to ISO8601 format from COOKIE format,
|
||||
* 'domain' and 'path' will be set from setter URL if empty.
|
||||
*
|
||||
* @param array cookie data, as returned by {@link HTTP_Request2_Response::getCookies()}
|
||||
* @param Net_URL2 URL of the document that sent Set-Cookie header
|
||||
* @param array $cookie cookie data, as returned by
|
||||
* {@link HTTP_Request2_Response::getCookies()}
|
||||
* @param Net_URL2 $setter URL of the document that sent Set-Cookie header
|
||||
*
|
||||
* @return array Updated cookie array
|
||||
* @throws HTTP_Request2_LogicException
|
||||
* @throws HTTP_Request2_MessageException
|
||||
@ -206,8 +213,10 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
/**
|
||||
* Stores a cookie in the jar
|
||||
*
|
||||
* @param array cookie data, as returned by {@link HTTP_Request2_Response::getCookies()}
|
||||
* @param Net_URL2 URL of the document that sent Set-Cookie header
|
||||
* @param array $cookie cookie data, as returned by
|
||||
* {@link HTTP_Request2_Response::getCookies()}
|
||||
* @param Net_URL2 $setter URL of the document that sent Set-Cookie header
|
||||
*
|
||||
* @throws HTTP_Request2_Exception
|
||||
*/
|
||||
public function store(array $cookie, Net_URL2 $setter = null)
|
||||
@ -233,9 +242,9 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
/**
|
||||
* Adds cookies set in HTTP response to the jar
|
||||
*
|
||||
* @param HTTP_Request2_Response response
|
||||
* @param Net_URL2 original request URL, needed for setting
|
||||
* default domain/path
|
||||
* @param HTTP_Request2_Response $response HTTP response message
|
||||
* @param Net_URL2 $setter original request URL, needed for
|
||||
* setting default domain/path
|
||||
*/
|
||||
public function addCookiesFromResponse(HTTP_Request2_Response $response, Net_URL2 $setter)
|
||||
{
|
||||
@ -252,9 +261,10 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
* - cookie path should be a prefix for request path
|
||||
* - 'secure' cookies will only be sent for HTTPS requests
|
||||
*
|
||||
* @param Net_URL2
|
||||
* @param bool Whether to return cookies as string for "Cookie: " header
|
||||
* @return array
|
||||
* @param Net_URL2 $url Request url
|
||||
* @param bool $asString Whether to return cookies as string for "Cookie: " header
|
||||
*
|
||||
* @return array|string Matching cookies
|
||||
*/
|
||||
public function getMatching(Net_URL2 $url, $asString = false)
|
||||
{
|
||||
@ -312,7 +322,7 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
/**
|
||||
* Sets whether session cookies should be serialized when serializing the jar
|
||||
*
|
||||
* @param boolean
|
||||
* @param boolean $serialize serialize?
|
||||
*/
|
||||
public function serializeSessionCookies($serialize)
|
||||
{
|
||||
@ -336,7 +346,8 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
* the license information in public-suffix-list.php), so you can disable
|
||||
* its use if this is an issue for you.
|
||||
*
|
||||
* @param boolean
|
||||
* @param boolean $useList use the list?
|
||||
*
|
||||
* @link http://publicsuffix.org/learn/
|
||||
*/
|
||||
public function usePublicSuffixList($useList)
|
||||
@ -348,6 +359,7 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
* Returns string representation of object
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see Serializable::serialize()
|
||||
*/
|
||||
public function serialize()
|
||||
@ -370,7 +382,8 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
/**
|
||||
* Constructs the object from serialized string
|
||||
*
|
||||
* @param string string representation
|
||||
* @param string $serialized string representation
|
||||
*
|
||||
* @see Serializable::unserialize()
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
@ -400,8 +413,9 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
* at given URL can set a cookie with a given domain attribute and by
|
||||
* {@link getMatching()} to find cookies matching the request URL.
|
||||
*
|
||||
* @param string request host
|
||||
* @param string cookie domain
|
||||
* @param string $requestHost request host
|
||||
* @param string $cookieDomain cookie domain
|
||||
*
|
||||
* @return bool match success
|
||||
*/
|
||||
public function domainMatch($requestHost, $cookieDomain)
|
||||
@ -432,7 +446,8 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
* domain ends and registered domain starts. It will remove domain parts
|
||||
* to the left of registered one.
|
||||
*
|
||||
* @param string domain name
|
||||
* @param string $domain domain name
|
||||
*
|
||||
* @return string|bool registered domain, will return false if $domain is
|
||||
* either invalid or a TLD itself
|
||||
*/
|
||||
@ -444,8 +459,10 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
if (empty(self::$psl)) {
|
||||
$path = '@data_dir@' . DIRECTORY_SEPARATOR . 'HTTP_Request2';
|
||||
if (0 === strpos($path, '@' . 'data_dir@')) {
|
||||
$path = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
|
||||
. DIRECTORY_SEPARATOR . 'data');
|
||||
$path = realpath(
|
||||
dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
|
||||
. DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data'
|
||||
);
|
||||
}
|
||||
self::$psl = include_once $path . DIRECTORY_SEPARATOR . 'public-suffix-list.php';
|
||||
}
|
||||
@ -469,8 +486,9 @@ class HTTP_Request2_CookieJar implements Serializable
|
||||
/**
|
||||
* Recursive helper method for {@link getRegisteredDomain()}
|
||||
*
|
||||
* @param array remaining domain parts
|
||||
* @param mixed node in {@link HTTP_Request2_CookieJar::$psl} to check
|
||||
* @param array $domainParts remaining domain parts
|
||||
* @param mixed $listNode node in {@link HTTP_Request2_CookieJar::$psl} to check
|
||||
*
|
||||
* @return string|null concatenated domain parts, null in case of error
|
||||
*/
|
||||
protected static function checkDomainsList(array $domainParts, $listNode)
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Exception.php 308629 2011-02-24 17:34:24Z avb $
|
||||
* @version SVN: $Id: Exception.php 324415 2012-03-21 10:50:50Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -51,7 +51,10 @@ require_once 'PEAR/Exception.php';
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @version Release: 2.0.0RC1
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=132
|
||||
*/
|
||||
class HTTP_Request2_Exception extends PEAR_Exception
|
||||
@ -85,9 +88,9 @@ class HTTP_Request2_Exception extends PEAR_Exception
|
||||
/**
|
||||
* Constructor, can set package error code and native error code
|
||||
*
|
||||
* @param string exception message
|
||||
* @param int package error code, one of class constants
|
||||
* @param int error code from underlying PHP extension
|
||||
* @param string $message exception message
|
||||
* @param int $code package error code, one of class constants
|
||||
* @param int $nativeCode error code from underlying PHP extension
|
||||
*/
|
||||
public function __construct($message = null, $code = null, $nativeCode = null)
|
||||
{
|
||||
@ -115,9 +118,14 @@ class HTTP_Request2_Exception extends PEAR_Exception
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @version Release: 2.0.0RC1
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception {}
|
||||
class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception that represents error in the program logic
|
||||
@ -131,9 +139,14 @@ class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception {}
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @version Release: 2.0.0RC1
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_LogicException extends HTTP_Request2_Exception {}
|
||||
class HTTP_Request2_LogicException extends HTTP_Request2_Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when connection to a web or proxy server fails
|
||||
@ -143,9 +156,14 @@ class HTTP_Request2_LogicException extends HTTP_Request2_Exception {}
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @version Release: 2.0.0RC1
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception {}
|
||||
class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when sending or receiving HTTP message fails
|
||||
@ -154,7 +172,12 @@ class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception {}
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @version Release: 2.0.0RC1
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_MessageException extends HTTP_Request2_Exception {}
|
||||
class HTTP_Request2_MessageException extends HTTP_Request2_Exception
|
||||
{
|
||||
}
|
||||
?>
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: MultipartBody.php 308322 2011-02-14 13:58:03Z avb $
|
||||
* @version SVN: $Id: MultipartBody.php 324415 2012-03-21 10:50:50Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -50,7 +50,9 @@
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @version Release: 2.0.0RC1
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
* @link http://tools.ietf.org/html/rfc1867
|
||||
*/
|
||||
class HTTP_Request2_MultipartBody
|
||||
@ -99,9 +101,11 @@ class HTTP_Request2_MultipartBody
|
||||
/**
|
||||
* Constructor. Sets the arrays with POST data.
|
||||
*
|
||||
* @param array values of form fields set via {@link HTTP_Request2::addPostParameter()}
|
||||
* @param array file uploads set via {@link HTTP_Request2::addUpload()}
|
||||
* @param bool whether to append brackets to array variable names
|
||||
* @param array $params values of form fields set via
|
||||
* {@link HTTP_Request2::addPostParameter()}
|
||||
* @param array $uploads file uploads set via
|
||||
* {@link HTTP_Request2::addUpload()}
|
||||
* @param bool $useBrackets whether to append brackets to array variable names
|
||||
*/
|
||||
public function __construct(array $params, array $uploads, $useBrackets = true)
|
||||
{
|
||||
@ -160,7 +164,8 @@ class HTTP_Request2_MultipartBody
|
||||
/**
|
||||
* Returns next chunk of request body
|
||||
*
|
||||
* @param integer Amount of bytes to read
|
||||
* @param integer $length Number of bytes to read
|
||||
*
|
||||
* @return string Up to $length bytes of data, empty string if at end
|
||||
*/
|
||||
public function read($length)
|
||||
@ -172,18 +177,18 @@ class HTTP_Request2_MultipartBody
|
||||
while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) {
|
||||
$oldLength = $length;
|
||||
if ($this->_pos[0] < $paramCount) {
|
||||
$param = sprintf($this->_headerParam, $boundary,
|
||||
$this->_params[$this->_pos[0]][0]) .
|
||||
$this->_params[$this->_pos[0]][1] . "\r\n";
|
||||
$param = sprintf(
|
||||
$this->_headerParam, $boundary, $this->_params[$this->_pos[0]][0]
|
||||
) . $this->_params[$this->_pos[0]][1] . "\r\n";
|
||||
$ret .= substr($param, $this->_pos[1], $length);
|
||||
$length -= min(strlen($param) - $this->_pos[1], $length);
|
||||
|
||||
} elseif ($this->_pos[0] < $paramCount + $uploadCount) {
|
||||
$pos = $this->_pos[0] - $paramCount;
|
||||
$header = sprintf($this->_headerUpload, $boundary,
|
||||
$this->_uploads[$pos]['name'],
|
||||
$this->_uploads[$pos]['filename'],
|
||||
$this->_uploads[$pos]['type']);
|
||||
$header = sprintf(
|
||||
$this->_headerUpload, $boundary, $this->_uploads[$pos]['name'],
|
||||
$this->_uploads[$pos]['filename'], $this->_uploads[$pos]['type']
|
||||
);
|
||||
if ($this->_pos[1] < strlen($header)) {
|
||||
$ret .= substr($header, $this->_pos[1], $length);
|
||||
$length -= min(strlen($header) - $this->_pos[1], $length);
|
||||
@ -246,9 +251,10 @@ class HTTP_Request2_MultipartBody
|
||||
* Helper function to change the (probably multidimensional) associative array
|
||||
* into the simple one.
|
||||
*
|
||||
* @param string name for item
|
||||
* @param mixed item's values
|
||||
* @param bool whether to append [] to array variables' names
|
||||
* @param string $name name for item
|
||||
* @param mixed $values item's values
|
||||
* @param bool $useBrackets whether to append [] to array variables' names
|
||||
*
|
||||
* @return array array with the following items: array('item name', 'item value');
|
||||
*/
|
||||
private static function _flattenArray($name, $values, $useBrackets)
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -38,7 +38,7 @@
|
||||
* @author David Jean Louis <izi@php.net>
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Log.php 308680 2011-02-25 17:40:17Z avb $
|
||||
* @version SVN: $Id: Log.php 324415 2012-03-21 10:50:50Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -87,7 +87,7 @@ require_once 'HTTP/Request2/Exception.php';
|
||||
* @author David Jean Louis <izi@php.net>
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.0.0RC1
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
class HTTP_Request2_Observer_Log implements SplObserver
|
||||
@ -171,10 +171,10 @@ class HTTP_Request2_Observer_Log implements SplObserver
|
||||
$this->log('> ' . $event['data'] . ' byte(s) sent');
|
||||
break;
|
||||
case 'receivedHeaders':
|
||||
$this->log(sprintf('< HTTP/%s %s %s',
|
||||
$event['data']->getVersion(),
|
||||
$event['data']->getStatus(),
|
||||
$event['data']->getReasonPhrase()));
|
||||
$this->log(sprintf(
|
||||
'< HTTP/%s %s %s', $event['data']->getVersion(),
|
||||
$event['data']->getStatus(), $event['data']->getReasonPhrase()
|
||||
));
|
||||
$headers = $event['data']->getHeader();
|
||||
foreach ($headers as $key => $val) {
|
||||
$this->log('< ' . $key . ': ' . $val);
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,7 +37,7 @@
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: Response.php 309921 2011-04-03 16:43:02Z avb $
|
||||
* @version SVN: $Id: Response.php 324936 2012-04-07 07:49:03Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
@ -66,11 +66,12 @@ require_once 'HTTP/Request2/Exception.php';
|
||||
* var_dump($response->getHeader(), $response->getCookies(), $response->getBody());
|
||||
* </code>
|
||||
*
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @version Release: 2.0.0RC1
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
* @link http://tools.ietf.org/html/rfc2616#section-6
|
||||
*/
|
||||
class HTTP_Request2_Response
|
||||
@ -203,12 +204,32 @@ class HTTP_Request2_Response
|
||||
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the default reason phrase for the given code or all reason phrases
|
||||
*
|
||||
* @param int $code Response code
|
||||
*
|
||||
* @return string|array|null Default reason phrase for $code if $code is given
|
||||
* (null if no phrase is available), array of all
|
||||
* reason phrases if $code is null
|
||||
* @link http://pear.php.net/bugs/18716
|
||||
*/
|
||||
public static function getDefaultReasonPhrase($code = null)
|
||||
{
|
||||
if (null === $code) {
|
||||
return self::$phrases;
|
||||
} else {
|
||||
return isset(self::$phrases[$code]) ? self::$phrases[$code] : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor, parses the response status line
|
||||
*
|
||||
* @param string Response status line (e.g. "HTTP/1.1 200 OK")
|
||||
* @param bool Whether body is still encoded by Content-Encoding
|
||||
* @param string Effective URL of the response
|
||||
* @param string $statusLine Response status line (e.g. "HTTP/1.1 200 OK")
|
||||
* @param bool $bodyEncoded Whether body is still encoded by Content-Encoding
|
||||
* @param string $effectiveUrl Effective URL of the response
|
||||
*
|
||||
* @throws HTTP_Request2_MessageException if status line is invalid according to spec
|
||||
*/
|
||||
public function __construct($statusLine, $bodyEncoded = true, $effectiveUrl = null)
|
||||
@ -221,11 +242,7 @@ class HTTP_Request2_Response
|
||||
}
|
||||
$this->version = $m[1];
|
||||
$this->code = intval($m[2]);
|
||||
if (!empty($m[3])) {
|
||||
$this->reasonPhrase = trim($m[3]);
|
||||
} elseif (!empty(self::$phrases[$this->code])) {
|
||||
$this->reasonPhrase = self::$phrases[$this->code];
|
||||
}
|
||||
$this->reasonPhrase = !empty($m[3]) ? trim($m[3]) : self::getDefaultReasonPhrase($this->code);
|
||||
$this->bodyEncoded = (bool)$bodyEncoded;
|
||||
$this->effectiveUrl = (string)$effectiveUrl;
|
||||
}
|
||||
@ -238,14 +255,14 @@ class HTTP_Request2_Response
|
||||
* response headers and triggers additional processing, so be sure to pass an
|
||||
* empty string in the end.
|
||||
*
|
||||
* @param string Line from HTTP response
|
||||
* @param string $headerLine Line from HTTP response
|
||||
*/
|
||||
public function parseHeaderLine($headerLine)
|
||||
{
|
||||
$headerLine = trim($headerLine, "\r\n");
|
||||
|
||||
// empty string signals the end of headers, process the received ones
|
||||
if ('' == $headerLine) {
|
||||
// empty string signals the end of headers, process the received ones
|
||||
if (!empty($this->headers['set-cookie'])) {
|
||||
$cookies = is_array($this->headers['set-cookie'])?
|
||||
$this->headers['set-cookie']:
|
||||
@ -261,8 +278,8 @@ class HTTP_Request2_Response
|
||||
}
|
||||
}
|
||||
|
||||
// string of the form header-name: header value
|
||||
} elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) {
|
||||
// string of the form header-name: header value
|
||||
$name = strtolower($m[1]);
|
||||
$value = trim($m[2]);
|
||||
if (empty($this->headers[$name])) {
|
||||
@ -275,8 +292,8 @@ class HTTP_Request2_Response
|
||||
}
|
||||
$this->lastHeader = $name;
|
||||
|
||||
// continuation of a previous header
|
||||
} elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) {
|
||||
// continuation of a previous header
|
||||
if (!is_array($this->headers[$this->lastHeader])) {
|
||||
$this->headers[$this->lastHeader] .= ' ' . trim($m[1]);
|
||||
} else {
|
||||
@ -289,7 +306,8 @@ class HTTP_Request2_Response
|
||||
/**
|
||||
* Parses a Set-Cookie header to fill $cookies array
|
||||
*
|
||||
* @param string value of Set-Cookie header
|
||||
* @param string $cookieString value of Set-Cookie header
|
||||
*
|
||||
* @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
|
||||
*/
|
||||
protected function parseCookie($cookieString)
|
||||
@ -301,14 +319,14 @@ class HTTP_Request2_Response
|
||||
'secure' => false
|
||||
);
|
||||
|
||||
// Only a name=value pair
|
||||
if (!strpos($cookieString, ';')) {
|
||||
// Only a name=value pair
|
||||
$pos = strpos($cookieString, '=');
|
||||
$cookie['name'] = trim(substr($cookieString, 0, $pos));
|
||||
$cookie['value'] = trim(substr($cookieString, $pos + 1));
|
||||
|
||||
// Some optional parameters are supplied
|
||||
} else {
|
||||
// Some optional parameters are supplied
|
||||
$elements = explode(';', $cookieString);
|
||||
$pos = strpos($elements[0], '=');
|
||||
$cookie['name'] = trim(substr($elements[0], 0, $pos));
|
||||
@ -338,7 +356,8 @@ class HTTP_Request2_Response
|
||||
|
||||
/**
|
||||
* Appends a string to the response body
|
||||
* @param string
|
||||
*
|
||||
* @param string $bodyChunk part of response body
|
||||
*/
|
||||
public function appendBody($bodyChunk)
|
||||
{
|
||||
@ -360,6 +379,7 @@ class HTTP_Request2_Response
|
||||
|
||||
/**
|
||||
* Returns the status code
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getStatus()
|
||||
@ -369,6 +389,7 @@ class HTTP_Request2_Response
|
||||
|
||||
/**
|
||||
* Returns the reason phrase
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReasonPhrase()
|
||||
@ -378,6 +399,7 @@ class HTTP_Request2_Response
|
||||
|
||||
/**
|
||||
* Whether response is a redirect that can be automatically handled by HTTP_Request2
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRedirect()
|
||||
@ -389,7 +411,8 @@ class HTTP_Request2_Response
|
||||
/**
|
||||
* Returns either the named header or all response headers
|
||||
*
|
||||
* @param string Name of header to return
|
||||
* @param string $headerName Name of header to return
|
||||
*
|
||||
* @return string|array Value of $headerName header (null if header is
|
||||
* not present), array of all response headers if
|
||||
* $headerName is null
|
||||
@ -422,15 +445,15 @@ class HTTP_Request2_Response
|
||||
*/
|
||||
public function getBody()
|
||||
{
|
||||
if (0 == strlen($this->body) || !$this->bodyEncoded ||
|
||||
!in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate'))
|
||||
if (0 == strlen($this->body) || !$this->bodyEncoded
|
||||
|| !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate'))
|
||||
) {
|
||||
return $this->body;
|
||||
|
||||
} else {
|
||||
if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
|
||||
$oldEncoding = mb_internal_encoding();
|
||||
mb_internal_encoding('iso-8859-1');
|
||||
mb_internal_encoding('8bit');
|
||||
}
|
||||
|
||||
try {
|
||||
@ -471,7 +494,8 @@ class HTTP_Request2_Response
|
||||
* method only parses the header and checks data for compliance with
|
||||
* RFC 1952
|
||||
*
|
||||
* @param string gzip-encoded data
|
||||
* @param string $data gzip-encoded data
|
||||
*
|
||||
* @return string decoded data
|
||||
* @throws HTTP_Request2_LogicException
|
||||
* @throws HTTP_Request2_MessageException
|
||||
@ -606,7 +630,8 @@ class HTTP_Request2_Response
|
||||
/**
|
||||
* Decodes the message-body encoded by deflate
|
||||
*
|
||||
* @param string deflate-encoded data
|
||||
* @param string $data deflate-encoded data
|
||||
*
|
||||
* @return string decoded data
|
||||
* @throws HTTP_Request2_LogicException
|
||||
*/
|
||||
|
158
extlib/HTTP/Request2/SOCKS5.php
Normal file
158
extlib/HTTP/Request2/SOCKS5.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/**
|
||||
* SOCKS5 proxy connection class
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: SOCKS5.php 324953 2012-04-08 07:24:12Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
/** Socket wrapper class used by Socket Adapter */
|
||||
require_once 'HTTP/Request2/SocketWrapper.php';
|
||||
|
||||
/**
|
||||
* SOCKS5 proxy connection class (used by Socket Adapter)
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
* @link http://pear.php.net/bugs/bug.php?id=19332
|
||||
* @link http://tools.ietf.org/html/rfc1928
|
||||
*/
|
||||
class HTTP_Request2_SOCKS5 extends HTTP_Request2_SocketWrapper
|
||||
{
|
||||
/**
|
||||
* Constructor, tries to connect and authenticate to a SOCKS5 proxy
|
||||
*
|
||||
* @param string $address Proxy address, e.g. 'tcp://localhost:1080'
|
||||
* @param int $timeout Connection timeout (seconds)
|
||||
* @param array $sslOptions SSL context options
|
||||
* @param string $username Proxy user name
|
||||
* @param string $password Proxy password
|
||||
*
|
||||
* @throws HTTP_Request2_LogicException
|
||||
* @throws HTTP_Request2_ConnectionException
|
||||
* @throws HTTP_Request2_MessageException
|
||||
*/
|
||||
public function __construct(
|
||||
$address, $timeout = 10, array $sslOptions = array(),
|
||||
$username = null, $password = null
|
||||
) {
|
||||
parent::__construct($address, $timeout, $sslOptions);
|
||||
|
||||
if (strlen($username)) {
|
||||
$request = pack('C4', 5, 2, 0, 2);
|
||||
} else {
|
||||
$request = pack('C3', 5, 1, 0);
|
||||
}
|
||||
$this->write($request);
|
||||
$response = unpack('Cversion/Cmethod', $this->read(3));
|
||||
if (5 != $response['version']) {
|
||||
throw new HTTP_Request2_MessageException(
|
||||
'Invalid version received from SOCKS5 proxy: ' . $response['version'],
|
||||
HTTP_Request2_Exception::MALFORMED_RESPONSE
|
||||
);
|
||||
}
|
||||
switch ($response['method']) {
|
||||
case 2:
|
||||
$this->performAuthentication($username, $password);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
throw new HTTP_Request2_ConnectionException(
|
||||
"Connection rejected by proxy due to unsupported auth method"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs username/password authentication for SOCKS5
|
||||
*
|
||||
* @param string $username Proxy user name
|
||||
* @param string $password Proxy password
|
||||
*
|
||||
* @throws HTTP_Request2_ConnectionException
|
||||
* @throws HTTP_Request2_MessageException
|
||||
* @link http://tools.ietf.org/html/rfc1929
|
||||
*/
|
||||
protected function performAuthentication($username, $password)
|
||||
{
|
||||
$request = pack('C2', 1, strlen($username)) . $username
|
||||
. pack('C', strlen($password)) . $password;
|
||||
|
||||
$this->write($request);
|
||||
$response = unpack('Cvn/Cstatus', $this->read(3));
|
||||
if (1 != $response['vn'] || 0 != $response['status']) {
|
||||
throw new HTTP_Request2_ConnectionException(
|
||||
'Connection rejected by proxy due to invalid username and/or password'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to a remote host via proxy
|
||||
*
|
||||
* @param string $remoteHost Remote host
|
||||
* @param int $remotePort Remote port
|
||||
*
|
||||
* @throws HTTP_Request2_ConnectionException
|
||||
* @throws HTTP_Request2_MessageException
|
||||
*/
|
||||
public function connect($remoteHost, $remotePort)
|
||||
{
|
||||
$request = pack('C5', 0x05, 0x01, 0x00, 0x03, strlen($remoteHost))
|
||||
. $remoteHost . pack('n', $remotePort);
|
||||
|
||||
$this->write($request);
|
||||
$response = unpack('Cversion/Creply/Creserved', $this->read(1024));
|
||||
if (5 != $response['version'] || 0 != $response['reserved']) {
|
||||
throw new HTTP_Request2_MessageException(
|
||||
'Invalid response received from SOCKS5 proxy',
|
||||
HTTP_Request2_Exception::MALFORMED_RESPONSE
|
||||
);
|
||||
} elseif (0 != $response['reply']) {
|
||||
throw new HTTP_Request2_ConnectionException(
|
||||
"Unable to connect to {$remoteHost}:{$remotePort} through SOCKS5 proxy",
|
||||
0, $response['reply']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
283
extlib/HTTP/Request2/SocketWrapper.php
Normal file
283
extlib/HTTP/Request2/SocketWrapper.php
Normal file
@ -0,0 +1,283 @@
|
||||
<?php
|
||||
/**
|
||||
* Socket wrapper class used by Socket Adapter
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version SVN: $Id: SocketWrapper.php 324935 2012-04-07 07:10:50Z avb $
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
*/
|
||||
|
||||
/** Exception classes for HTTP_Request2 package */
|
||||
require_once 'HTTP/Request2/Exception.php';
|
||||
|
||||
/**
|
||||
* Socket wrapper class used by Socket Adapter
|
||||
*
|
||||
* Needed to properly handle connection errors, global timeout support and
|
||||
* similar things. Loosely based on Net_Socket used by older HTTP_Request.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Request2
|
||||
* @author Alexey Borzov <avb@php.net>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: 2.1.1
|
||||
* @link http://pear.php.net/package/HTTP_Request2
|
||||
* @link http://pear.php.net/bugs/bug.php?id=19332
|
||||
* @link http://tools.ietf.org/html/rfc1928
|
||||
*/
|
||||
class HTTP_Request2_SocketWrapper
|
||||
{
|
||||
/**
|
||||
* PHP warning messages raised during stream_socket_client() call
|
||||
* @var array
|
||||
*/
|
||||
protected $connectionWarnings = array();
|
||||
|
||||
/**
|
||||
* Connected socket
|
||||
* @var resource
|
||||
*/
|
||||
protected $socket;
|
||||
|
||||
/**
|
||||
* Sum of start time and global timeout, exception will be thrown if request continues past this time
|
||||
* @var integer
|
||||
*/
|
||||
protected $deadline;
|
||||
|
||||
/**
|
||||
* Global timeout value, mostly for exception messages
|
||||
* @var integer
|
||||
*/
|
||||
protected $timeout;
|
||||
|
||||
/**
|
||||
* Class constructor, tries to establish connection
|
||||
*
|
||||
* @param string $address Address for stream_socket_client() call,
|
||||
* e.g. 'tcp://localhost:80'
|
||||
* @param int $timeout Connection timeout (seconds)
|
||||
* @param array $sslOptions SSL context options
|
||||
*
|
||||
* @throws HTTP_Request2_LogicException
|
||||
* @throws HTTP_Request2_ConnectionException
|
||||
*/
|
||||
public function __construct($address, $timeout, array $sslOptions = array())
|
||||
{
|
||||
$context = stream_context_create();
|
||||
foreach ($sslOptions as $name => $value) {
|
||||
if (!stream_context_set_option($context, 'ssl', $name, $value)) {
|
||||
throw new HTTP_Request2_LogicException(
|
||||
"Error setting SSL context option '{$name}'"
|
||||
);
|
||||
}
|
||||
}
|
||||
set_error_handler(array($this, 'connectionWarningsHandler'));
|
||||
$this->socket = stream_socket_client(
|
||||
$address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context
|
||||
);
|
||||
restore_error_handler();
|
||||
if (!$this->socket) {
|
||||
$error = $errstr ? $errstr : implode("\n", $this->connectionWarnings);
|
||||
throw new HTTP_Request2_ConnectionException(
|
||||
"Unable to connect to {$address}. Error: {$error}", 0, $errno
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor, disconnects socket
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
fclose($this->socket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around fread(), handles global request timeout
|
||||
*
|
||||
* @param int $length Reads up to this number of bytes
|
||||
*
|
||||
* @return string Data read from socket
|
||||
* @throws HTTP_Request2_MessageException In case of timeout
|
||||
*/
|
||||
public function read($length)
|
||||
{
|
||||
if ($this->deadline) {
|
||||
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
|
||||
}
|
||||
$data = fread($this->socket, $length);
|
||||
$this->checkTimeout();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads until either the end of the socket or a newline, whichever comes first
|
||||
*
|
||||
* Strips the trailing newline from the returned data, handles global
|
||||
* request timeout. Method idea borrowed from Net_Socket PEAR package.
|
||||
*
|
||||
* @param int $bufferSize buffer size to use for reading
|
||||
*
|
||||
* @return string Available data up to the newline (not including newline)
|
||||
* @throws HTTP_Request2_MessageException In case of timeout
|
||||
*/
|
||||
public function readLine($bufferSize)
|
||||
{
|
||||
$line = '';
|
||||
while (!feof($this->socket)) {
|
||||
if ($this->deadline) {
|
||||
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
|
||||
}
|
||||
$line .= @fgets($this->socket, $bufferSize);
|
||||
$this->checkTimeout();
|
||||
if (substr($line, -1) == "\n") {
|
||||
return rtrim($line, "\r\n");
|
||||
}
|
||||
}
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around fwrite(), handles global request timeout
|
||||
*
|
||||
* @param string $data String to be written
|
||||
*
|
||||
* @return int
|
||||
* @throws HTTP_Request2_MessageException
|
||||
*/
|
||||
public function write($data)
|
||||
{
|
||||
if ($this->deadline) {
|
||||
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
|
||||
}
|
||||
$written = fwrite($this->socket, $data);
|
||||
$this->checkTimeout();
|
||||
// http://www.php.net/manual/en/function.fwrite.php#96951
|
||||
if ($written < strlen($data)) {
|
||||
throw new HTTP_Request2_MessageException('Error writing request');
|
||||
}
|
||||
return $written;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for end-of-file on a socket
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function eof()
|
||||
{
|
||||
return feof($this->socket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets request deadline
|
||||
*
|
||||
* @param int $deadline Exception will be thrown if request continues
|
||||
* past this time
|
||||
* @param int $timeout Original request timeout value, to use in
|
||||
* Exception message
|
||||
*/
|
||||
public function setDeadline($deadline, $timeout)
|
||||
{
|
||||
$this->deadline = $deadline;
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on encryption on a socket
|
||||
*
|
||||
* @throws HTTP_Request2_ConnectionException
|
||||
*/
|
||||
public function enableCrypto()
|
||||
{
|
||||
$modes = array(
|
||||
STREAM_CRYPTO_METHOD_TLS_CLIENT,
|
||||
STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
|
||||
STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
|
||||
STREAM_CRYPTO_METHOD_SSLv2_CLIENT
|
||||
);
|
||||
|
||||
foreach ($modes as $mode) {
|
||||
if (stream_socket_enable_crypto($this->socket, true, $mode)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new HTTP_Request2_ConnectionException(
|
||||
'Failed to enable secure connection when connecting through proxy'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an Exception if stream timed out
|
||||
*
|
||||
* @throws HTTP_Request2_MessageException
|
||||
*/
|
||||
protected function checkTimeout()
|
||||
{
|
||||
$info = stream_get_meta_data($this->socket);
|
||||
if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {
|
||||
$reason = $this->deadline
|
||||
? "after {$this->timeout} second(s)"
|
||||
: 'due to default_socket_timeout php.ini setting';
|
||||
throw new HTTP_Request2_MessageException(
|
||||
"Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error handler to use during stream_socket_client() call
|
||||
*
|
||||
* One stream_socket_client() call may produce *multiple* PHP warnings
|
||||
* (especially OpenSSL-related), we keep them in an array to later use for
|
||||
* the message of HTTP_Request2_ConnectionException
|
||||
*
|
||||
* @param int $errno error level
|
||||
* @param string $errstr error message
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function connectionWarningsHandler($errno, $errstr)
|
||||
{
|
||||
if ($errno & E_WARNING) {
|
||||
array_unshift($this->connectionWarnings, $errstr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,485 +0,0 @@
|
||||
<?php
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | Copyright (c) 2002-2004, Richard Heyes |
|
||||
// | All rights reserved. |
|
||||
// | |
|
||||
// | Redistribution and use in source and binary forms, with or without |
|
||||
// | modification, are permitted provided that the following conditions |
|
||||
// | are met: |
|
||||
// | |
|
||||
// | o Redistributions of source code must retain the above copyright |
|
||||
// | notice, this list of conditions and the following disclaimer. |
|
||||
// | o Redistributions in binary form must reproduce the above copyright |
|
||||
// | notice, this list of conditions and the following disclaimer in the |
|
||||
// | documentation and/or other materials provided with the distribution.|
|
||||
// | o The names of the authors may not be used to endorse or promote |
|
||||
// | products derived from this software without specific prior written |
|
||||
// | permission. |
|
||||
// | |
|
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
||||
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
||||
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
||||
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
||||
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
||||
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
||||
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
||||
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
||||
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||
// | |
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | Author: Richard Heyes <richard at php net> |
|
||||
// +-----------------------------------------------------------------------+
|
||||
//
|
||||
// $Id: URL.php,v 1.49 2007/06/28 14:43:07 davidc Exp $
|
||||
//
|
||||
// Net_URL Class
|
||||
|
||||
|
||||
class Net_URL
|
||||
{
|
||||
var $options = array('encode_query_keys' => false);
|
||||
/**
|
||||
* Full url
|
||||
* @var string
|
||||
*/
|
||||
var $url;
|
||||
|
||||
/**
|
||||
* Protocol
|
||||
* @var string
|
||||
*/
|
||||
var $protocol;
|
||||
|
||||
/**
|
||||
* Username
|
||||
* @var string
|
||||
*/
|
||||
var $username;
|
||||
|
||||
/**
|
||||
* Password
|
||||
* @var string
|
||||
*/
|
||||
var $password;
|
||||
|
||||
/**
|
||||
* Host
|
||||
* @var string
|
||||
*/
|
||||
var $host;
|
||||
|
||||
/**
|
||||
* Port
|
||||
* @var integer
|
||||
*/
|
||||
var $port;
|
||||
|
||||
/**
|
||||
* Path
|
||||
* @var string
|
||||
*/
|
||||
var $path;
|
||||
|
||||
/**
|
||||
* Query string
|
||||
* @var array
|
||||
*/
|
||||
var $querystring;
|
||||
|
||||
/**
|
||||
* Anchor
|
||||
* @var string
|
||||
*/
|
||||
var $anchor;
|
||||
|
||||
/**
|
||||
* Whether to use []
|
||||
* @var bool
|
||||
*/
|
||||
var $useBrackets;
|
||||
|
||||
/**
|
||||
* PHP4 Constructor
|
||||
*
|
||||
* @see __construct()
|
||||
*/
|
||||
function Net_URL($url = null, $useBrackets = true)
|
||||
{
|
||||
$this->__construct($url, $useBrackets);
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP5 Constructor
|
||||
*
|
||||
* Parses the given url and stores the various parts
|
||||
* Defaults are used in certain cases
|
||||
*
|
||||
* @param string $url Optional URL
|
||||
* @param bool $useBrackets Whether to use square brackets when
|
||||
* multiple querystrings with the same name
|
||||
* exist
|
||||
*/
|
||||
function __construct($url = null, $useBrackets = true)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->useBrackets = $useBrackets;
|
||||
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
function initialize()
|
||||
{
|
||||
$HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
|
||||
|
||||
$this->user = '';
|
||||
$this->pass = '';
|
||||
$this->host = '';
|
||||
$this->port = 80;
|
||||
$this->path = '';
|
||||
$this->querystring = array();
|
||||
$this->anchor = '';
|
||||
|
||||
// Only use defaults if not an absolute URL given
|
||||
if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) {
|
||||
$this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
|
||||
|
||||
/**
|
||||
* Figure out host/port
|
||||
*/
|
||||
if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) &&
|
||||
preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches))
|
||||
{
|
||||
$host = $matches[1];
|
||||
if (!empty($matches[3])) {
|
||||
$port = $matches[3];
|
||||
} else {
|
||||
$port = $this->getStandardPort($this->protocol);
|
||||
}
|
||||
}
|
||||
|
||||
$this->user = '';
|
||||
$this->pass = '';
|
||||
$this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
|
||||
$this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
|
||||
$this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
|
||||
$this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
|
||||
$this->anchor = '';
|
||||
}
|
||||
|
||||
// Parse the url and store the various parts
|
||||
if (!empty($this->url)) {
|
||||
$urlinfo = parse_url($this->url);
|
||||
|
||||
// Default querystring
|
||||
$this->querystring = array();
|
||||
|
||||
foreach ($urlinfo as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'scheme':
|
||||
$this->protocol = $value;
|
||||
$this->port = $this->getStandardPort($value);
|
||||
break;
|
||||
|
||||
case 'user':
|
||||
case 'pass':
|
||||
case 'host':
|
||||
case 'port':
|
||||
$this->$key = $value;
|
||||
break;
|
||||
|
||||
case 'path':
|
||||
if ($value{0} == '/') {
|
||||
$this->path = $value;
|
||||
} else {
|
||||
$path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
|
||||
$this->path = sprintf('%s/%s', $path, $value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'query':
|
||||
$this->querystring = $this->_parseRawQueryString($value);
|
||||
break;
|
||||
|
||||
case 'fragment':
|
||||
$this->anchor = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns full url
|
||||
*
|
||||
* @return string Full url
|
||||
* @access public
|
||||
*/
|
||||
function getURL()
|
||||
{
|
||||
$querystring = $this->getQueryString();
|
||||
|
||||
$this->url = $this->protocol . '://'
|
||||
. $this->user . (!empty($this->pass) ? ':' : '')
|
||||
. $this->pass . (!empty($this->user) ? '@' : '')
|
||||
. $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
|
||||
. $this->path
|
||||
. (!empty($querystring) ? '?' . $querystring : '')
|
||||
. (!empty($this->anchor) ? '#' . $this->anchor : '');
|
||||
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or updates a querystring item (URL parameter).
|
||||
* Automatically encodes parameters with rawurlencode() if $preencoded
|
||||
* is false.
|
||||
* You can pass an array to $value, it gets mapped via [] in the URL if
|
||||
* $this->useBrackets is activated.
|
||||
*
|
||||
* @param string $name Name of item
|
||||
* @param string $value Value of item
|
||||
* @param bool $preencoded Whether value is urlencoded or not, default = not
|
||||
* @access public
|
||||
*/
|
||||
function addQueryString($name, $value, $preencoded = false)
|
||||
{
|
||||
if ($this->getOption('encode_query_keys')) {
|
||||
$name = rawurlencode($name);
|
||||
}
|
||||
|
||||
if ($preencoded) {
|
||||
$this->querystring[$name] = $value;
|
||||
} else {
|
||||
$this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a querystring item
|
||||
*
|
||||
* @param string $name Name of item
|
||||
* @access public
|
||||
*/
|
||||
function removeQueryString($name)
|
||||
{
|
||||
if ($this->getOption('encode_query_keys')) {
|
||||
$name = rawurlencode($name);
|
||||
}
|
||||
|
||||
if (isset($this->querystring[$name])) {
|
||||
unset($this->querystring[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the querystring to literally what you supply
|
||||
*
|
||||
* @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc
|
||||
* @access public
|
||||
*/
|
||||
function addRawQueryString($querystring)
|
||||
{
|
||||
$this->querystring = $this->_parseRawQueryString($querystring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns flat querystring
|
||||
*
|
||||
* @return string Querystring
|
||||
* @access public
|
||||
*/
|
||||
function getQueryString()
|
||||
{
|
||||
if (!empty($this->querystring)) {
|
||||
foreach ($this->querystring as $name => $value) {
|
||||
// Encode var name
|
||||
$name = rawurlencode($name);
|
||||
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $k => $v) {
|
||||
$querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
|
||||
}
|
||||
} elseif (!is_null($value)) {
|
||||
$querystring[] = $name . '=' . $value;
|
||||
} else {
|
||||
$querystring[] = $name;
|
||||
}
|
||||
}
|
||||
$querystring = implode(ini_get('arg_separator.output'), $querystring);
|
||||
} else {
|
||||
$querystring = '';
|
||||
}
|
||||
|
||||
return $querystring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses raw querystring and returns an array of it
|
||||
*
|
||||
* @param string $querystring The querystring to parse
|
||||
* @return array An array of the querystring data
|
||||
* @access private
|
||||
*/
|
||||
function _parseRawQuerystring($querystring)
|
||||
{
|
||||
$parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$return = array();
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if (strpos($part, '=') !== false) {
|
||||
$value = substr($part, strpos($part, '=') + 1);
|
||||
$key = substr($part, 0, strpos($part, '='));
|
||||
} else {
|
||||
$value = null;
|
||||
$key = $part;
|
||||
}
|
||||
|
||||
if (!$this->getOption('encode_query_keys')) {
|
||||
$key = rawurldecode($key);
|
||||
}
|
||||
|
||||
if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
|
||||
$key = $matches[1];
|
||||
$idx = $matches[2];
|
||||
|
||||
// Ensure is an array
|
||||
if (empty($return[$key]) || !is_array($return[$key])) {
|
||||
$return[$key] = array();
|
||||
}
|
||||
|
||||
// Add data
|
||||
if ($idx === '') {
|
||||
$return[$key][] = $value;
|
||||
} else {
|
||||
$return[$key][$idx] = $value;
|
||||
}
|
||||
} elseif (!$this->useBrackets AND !empty($return[$key])) {
|
||||
$return[$key] = (array)$return[$key];
|
||||
$return[$key][] = $value;
|
||||
} else {
|
||||
$return[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves //, ../ and ./ from a path and returns
|
||||
* the result. Eg:
|
||||
*
|
||||
* /foo/bar/../boo.php => /foo/boo.php
|
||||
* /foo/bar/../../boo.php => /boo.php
|
||||
* /foo/bar/.././/boo.php => /foo/boo.php
|
||||
*
|
||||
* This method can also be called statically.
|
||||
*
|
||||
* @param string $path URL path to resolve
|
||||
* @return string The result
|
||||
*/
|
||||
function resolvePath($path)
|
||||
{
|
||||
$path = explode('/', str_replace('//', '/', $path));
|
||||
|
||||
for ($i=0; $i<count($path); $i++) {
|
||||
if ($path[$i] == '.') {
|
||||
unset($path[$i]);
|
||||
$path = array_values($path);
|
||||
$i--;
|
||||
|
||||
} elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
|
||||
unset($path[$i]);
|
||||
unset($path[$i-1]);
|
||||
$path = array_values($path);
|
||||
$i -= 2;
|
||||
|
||||
} elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
|
||||
unset($path[$i]);
|
||||
$path = array_values($path);
|
||||
$i--;
|
||||
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return implode('/', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard port number for a protocol
|
||||
*
|
||||
* @param string $scheme The protocol to lookup
|
||||
* @return integer Port number or NULL if no scheme matches
|
||||
*
|
||||
* @author Philippe Jausions <Philippe.Jausions@11abacus.com>
|
||||
*/
|
||||
function getStandardPort($scheme)
|
||||
{
|
||||
switch (strtolower($scheme)) {
|
||||
case 'http': return 80;
|
||||
case 'https': return 443;
|
||||
case 'ftp': return 21;
|
||||
case 'imap': return 143;
|
||||
case 'imaps': return 993;
|
||||
case 'pop3': return 110;
|
||||
case 'pop3s': return 995;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the URL to a particular protocol
|
||||
*
|
||||
* @param string $protocol Protocol to force the URL to
|
||||
* @param integer $port Optional port (standard port is used by default)
|
||||
*/
|
||||
function setProtocol($protocol, $port = null)
|
||||
{
|
||||
$this->protocol = $protocol;
|
||||
$this->port = is_null($port) ? $this->getStandardPort($protocol) : $port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an option
|
||||
*
|
||||
* This function set an option
|
||||
* to be used thorough the script.
|
||||
*
|
||||
* @access public
|
||||
* @param string $optionName The optionname to set
|
||||
* @param string $value The value of this option.
|
||||
*/
|
||||
function setOption($optionName, $value)
|
||||
{
|
||||
if (!array_key_exists($optionName, $this->options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->options[$optionName] = $value;
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an option
|
||||
*
|
||||
* This function gets an option
|
||||
* from the $this->options array
|
||||
* and return it's value.
|
||||
*
|
||||
* @access public
|
||||
* @param string $opionName The name of the option to retrieve
|
||||
* @see $this->options
|
||||
*/
|
||||
function getOption($optionName)
|
||||
{
|
||||
if (!isset($this->options[$optionName])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->options[$optionName];
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
210
extlib/Net/URL2.php
Normal file → Executable file
210
extlib/Net/URL2.php
Normal file → Executable file
@ -18,9 +18,9 @@
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the PHP_LexerGenerator nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* * Neither the name of the Net_URL2 nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
@ -36,10 +36,10 @@
|
||||
*
|
||||
* @category Networking
|
||||
* @package Net_URL2
|
||||
* @author Christian Schmidt <chsc@peytz.dk>
|
||||
* @copyright 2007-2008 Peytz & Co. A/S
|
||||
* @author Christian Schmidt <schmidt@php.net>
|
||||
* @copyright 2007-2009 Peytz & Co. A/S
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: URL2.php 286661 2009-08-02 12:50:54Z schmidt $
|
||||
* @version CVS: $Id: URL2.php 309223 2011-03-14 14:26:32Z till $
|
||||
* @link http://www.rfc-editor.org/rfc/rfc3986.txt
|
||||
*/
|
||||
|
||||
@ -48,8 +48,8 @@
|
||||
*
|
||||
* @category Networking
|
||||
* @package Net_URL2
|
||||
* @author Christian Schmidt <chsc@peytz.dk>
|
||||
* @copyright 2007-2008 Peytz & Co. ApS
|
||||
* @author Christian Schmidt <schmidt@php.net>
|
||||
* @copyright 2007-2009 Peytz & Co. A/S
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/Net_URL2
|
||||
@ -74,15 +74,13 @@ class Net_URL2
|
||||
|
||||
/**
|
||||
* Query variable separators when parsing the query string. Every character
|
||||
* is considered a separator. Default is specified by the
|
||||
* arg_separator.input php.ini setting (this defaults to "&").
|
||||
* is considered a separator. Default is "&".
|
||||
*/
|
||||
const OPTION_SEPARATOR_INPUT = 'input_separator';
|
||||
|
||||
/**
|
||||
* Query variable separator used when generating the query string. Default
|
||||
* is specified by the arg_separator.output php.ini setting (this defaults
|
||||
* to "&").
|
||||
* is "&".
|
||||
*/
|
||||
const OPTION_SEPARATOR_OUTPUT = 'output_separator';
|
||||
|
||||
@ -93,8 +91,8 @@ class Net_URL2
|
||||
self::OPTION_STRICT => true,
|
||||
self::OPTION_USE_BRACKETS => true,
|
||||
self::OPTION_ENCODE_KEYS => true,
|
||||
self::OPTION_SEPARATOR_INPUT => 'x&',
|
||||
self::OPTION_SEPARATOR_OUTPUT => 'x&',
|
||||
self::OPTION_SEPARATOR_INPUT => '&',
|
||||
self::OPTION_SEPARATOR_OUTPUT => '&',
|
||||
);
|
||||
|
||||
/**
|
||||
@ -113,7 +111,7 @@ class Net_URL2
|
||||
private $_host = false;
|
||||
|
||||
/**
|
||||
* @var int|bool
|
||||
* @var string|bool
|
||||
*/
|
||||
private $_port = false;
|
||||
|
||||
@ -137,41 +135,19 @@ class Net_URL2
|
||||
*
|
||||
* @param string $url an absolute or relative URL
|
||||
* @param array $options an array of OPTION_xxx constants
|
||||
*
|
||||
* @return $this
|
||||
* @uses self::parseUrl()
|
||||
*/
|
||||
public function __construct($url, $options = null)
|
||||
public function __construct($url, array $options = array())
|
||||
{
|
||||
$this->setOption(self::OPTION_SEPARATOR_INPUT,
|
||||
ini_get('arg_separator.input'));
|
||||
$this->setOption(self::OPTION_SEPARATOR_OUTPUT,
|
||||
ini_get('arg_separator.output'));
|
||||
if (is_array($options)) {
|
||||
foreach ($options as $optionName => $value) {
|
||||
$this->setOption($optionName, $value);
|
||||
if (array_key_exists($optionName, $this->_options)) {
|
||||
$this->_options[$optionName] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
|
||||
$this->_scheme = $reg[1];
|
||||
$url = substr($url, strlen($reg[0]));
|
||||
}
|
||||
|
||||
if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
|
||||
$this->setAuthority($reg[1]);
|
||||
$url = substr($url, strlen($reg[0]));
|
||||
}
|
||||
|
||||
$i = strcspn($url, '?#');
|
||||
$this->_path = substr($url, 0, $i);
|
||||
$url = substr($url, $i);
|
||||
|
||||
if (preg_match('@^\?([^#]*)@', $url, $reg)) {
|
||||
$this->_query = $reg[1];
|
||||
$url = substr($url, strlen($reg[0]));
|
||||
}
|
||||
|
||||
if ($url) {
|
||||
$this->_fragment = substr($url, 1);
|
||||
}
|
||||
$this->parseUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,12 +208,13 @@ class Net_URL2
|
||||
* scheme specified, i.e. if this is a relative
|
||||
* URL
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
* @see getScheme()
|
||||
*/
|
||||
public function setScheme($scheme)
|
||||
{
|
||||
$this->_scheme = $scheme;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -286,7 +263,7 @@ class Net_URL2
|
||||
* @param string|bool $userinfo userinfo or username
|
||||
* @param string|bool $password optional password, or false
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function setUserinfo($userinfo, $password = false)
|
||||
{
|
||||
@ -294,6 +271,7 @@ class Net_URL2
|
||||
if ($password !== false) {
|
||||
$this->_userinfo .= ':' . $password;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,18 +291,19 @@ class Net_URL2
|
||||
*
|
||||
* @param string|bool $host a hostname, an IP address, or false
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function setHost($host)
|
||||
{
|
||||
$this->_host = $host;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port number, or false if there is no port number specified,
|
||||
* i.e. if the default port is to be used.
|
||||
*
|
||||
* @return int|bool
|
||||
* @return string|bool
|
||||
*/
|
||||
public function getPort()
|
||||
{
|
||||
@ -335,13 +314,14 @@ class Net_URL2
|
||||
* Sets the port number. Specify false if there is no port number specified,
|
||||
* i.e. if the default port is to be used.
|
||||
*
|
||||
* @param int|bool $port a port number, or false
|
||||
* @param string|bool $port a port number, or false
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function setPort($port)
|
||||
{
|
||||
$this->_port = intval($port);
|
||||
$this->_port = $port;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,7 +359,7 @@ class Net_URL2
|
||||
* with userinfo prefixed and port number
|
||||
* appended, e.g. "foo:bar@example.org:81".
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuthority($authority)
|
||||
{
|
||||
@ -393,9 +373,10 @@ class Net_URL2
|
||||
|
||||
$this->_host = $reg[3];
|
||||
if (isset($reg[5])) {
|
||||
$this->_port = intval($reg[5]);
|
||||
$this->_port = $reg[5];
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -413,11 +394,12 @@ class Net_URL2
|
||||
*
|
||||
* @param string $path a path
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function setPath($path)
|
||||
{
|
||||
$this->_path = $path;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -438,12 +420,13 @@ class Net_URL2
|
||||
*
|
||||
* @param string|bool $query a query string, e.g. "foo=1&bar=2"
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
* @see self::setQueryVariables()
|
||||
*/
|
||||
public function setQuery($query)
|
||||
{
|
||||
$this->_query = $query;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -462,11 +445,12 @@ class Net_URL2
|
||||
* @param string|bool $fragment a fragment excluding the leading "#", or
|
||||
* false
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function setFragment($fragment)
|
||||
{
|
||||
$this->_fragment = $fragment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -532,33 +516,19 @@ class Net_URL2
|
||||
*
|
||||
* @param array $array (name => value) array
|
||||
*
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function setQueryVariables(array $array)
|
||||
{
|
||||
if (!$array) {
|
||||
$this->_query = false;
|
||||
} else {
|
||||
foreach ($array as $name => $value) {
|
||||
if ($this->getOption(self::OPTION_ENCODE_KEYS)) {
|
||||
$name = self::urlencode($name);
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $k => $v) {
|
||||
$parts[] = $this->getOption(self::OPTION_USE_BRACKETS)
|
||||
? sprintf('%s[%s]=%s', $name, $k, $v)
|
||||
: ($name . '=' . $v);
|
||||
}
|
||||
} elseif (!is_null($value)) {
|
||||
$parts[] = $name . '=' . self::urlencode($value);
|
||||
} else {
|
||||
$parts[] = $name;
|
||||
}
|
||||
}
|
||||
$this->_query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT),
|
||||
$parts);
|
||||
$this->_query = $this->buildQuery(
|
||||
$array,
|
||||
$this->getOption(self::OPTION_SEPARATOR_OUTPUT)
|
||||
);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -567,13 +537,14 @@ class Net_URL2
|
||||
* @param string $name variable name
|
||||
* @param mixed $value variable value
|
||||
*
|
||||
* @return array
|
||||
* @return $this
|
||||
*/
|
||||
public function setQueryVariable($name, $value)
|
||||
{
|
||||
$array = $this->getQueryVariables();
|
||||
$array[$name] = $value;
|
||||
$this->setQueryVariables($array);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -832,6 +803,7 @@ class Net_URL2
|
||||
public static function urlencode($string)
|
||||
{
|
||||
$encoded = rawurlencode($string);
|
||||
|
||||
// This is only necessary in PHP < 5.3.
|
||||
$encoded = str_replace('%7E', '~', $encoded);
|
||||
return $encoded;
|
||||
@ -854,7 +826,7 @@ class Net_URL2
|
||||
$url = new self($_SERVER['PHP_SELF']);
|
||||
$url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
|
||||
$url->_host = $_SERVER['SERVER_NAME'];
|
||||
$port = intval($_SERVER['SERVER_PORT']);
|
||||
$port = $_SERVER['SERVER_PORT'];
|
||||
if ($url->_scheme == 'http' && $port != 80 ||
|
||||
$url->_scheme == 'https' && $port != 443) {
|
||||
|
||||
@ -894,25 +866,6 @@ class Net_URL2
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified option.
|
||||
*
|
||||
* @param string $optionName a self::OPTION_ constant
|
||||
* @param mixed $value option value
|
||||
*
|
||||
* @return void
|
||||
* @see self::OPTION_STRICT
|
||||
* @see self::OPTION_USE_BRACKETS
|
||||
* @see self::OPTION_ENCODE_KEYS
|
||||
*/
|
||||
function setOption($optionName, $value)
|
||||
{
|
||||
if (!array_key_exists($optionName, $this->_options)) {
|
||||
return false;
|
||||
}
|
||||
$this->_options[$optionName] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified option.
|
||||
*
|
||||
@ -920,9 +873,70 @@ class Net_URL2
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getOption($optionName)
|
||||
public function getOption($optionName)
|
||||
{
|
||||
return isset($this->_options[$optionName])
|
||||
? $this->_options[$optionName] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple version of http_build_query in userland. The encoded string is
|
||||
* percentage encoded according to RFC 3986.
|
||||
*
|
||||
* @param array $data An array, which has to be converted into
|
||||
* QUERY_STRING. Anything is possible.
|
||||
* @param string $seperator See {@link self::OPTION_SEPARATOR_OUTPUT}
|
||||
* @param string $key For stacked values (arrays in an array).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildQuery(array $data, $separator, $key = null)
|
||||
{
|
||||
$query = array();
|
||||
foreach ($data as $name => $value) {
|
||||
if ($this->getOption(self::OPTION_ENCODE_KEYS) === true) {
|
||||
$name = rawurlencode($name);
|
||||
}
|
||||
if ($key !== null) {
|
||||
if ($this->getOption(self::OPTION_USE_BRACKETS) === true) {
|
||||
$name = $key . '[' . $name . ']';
|
||||
} else {
|
||||
$name = $key;
|
||||
}
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$query[] = $this->buildQuery($value, $separator, $name);
|
||||
} else {
|
||||
$query[] = $name . '=' . rawurlencode($value);
|
||||
}
|
||||
}
|
||||
return implode($separator, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method uses a funky regex to parse the url into the designated parts.
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return void
|
||||
* @uses self::$_scheme, self::setAuthority(), self::$_path, self::$_query,
|
||||
* self::$_fragment
|
||||
* @see self::__construct()
|
||||
*/
|
||||
protected function parseUrl($url)
|
||||
{
|
||||
// The regular expression is copied verbatim from RFC 3986, appendix B.
|
||||
// The expression does not validate the URL but matches any string.
|
||||
preg_match('!^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?!',
|
||||
$url,
|
||||
$matches);
|
||||
|
||||
// "path" is always present (possibly as an empty string); the rest
|
||||
// are optional.
|
||||
$this->_scheme = !empty($matches[1]) ? $matches[2] : false;
|
||||
$this->setAuthority(!empty($matches[3]) ? $matches[4] : false);
|
||||
$this->_path = $matches[5];
|
||||
$this->_query = !empty($matches[6]) ? $matches[7] : false;
|
||||
$this->_fragment = !empty($matches[8]) ? $matches[9] : false;
|
||||
}
|
||||
}
|
||||
|
98
extlib/data/generate-list.php
Normal file
98
extlib/data/generate-list.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper file for downloading Public Suffix List and converting it to PHP array
|
||||
*
|
||||
* You can run this script to update PSL to the current version instead of
|
||||
* waiting for a new release of HTTP_Request2.
|
||||
*
|
||||
* @version SVN: $Id: generate-list.php 308480 2011-02-19 11:27:13Z avb $
|
||||
*/
|
||||
|
||||
/** URL to download Public Suffix List from */
|
||||
define('LIST_URL', 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1');
|
||||
/** Name of PHP file to write */
|
||||
define('OUTPUT_FILE', dirname(__FILE__) . '/public-suffix-list.php');
|
||||
|
||||
require_once 'HTTP/Request2.php';
|
||||
|
||||
function buildSubdomain(&$node, $tldParts)
|
||||
{
|
||||
$part = trim(array_pop($tldParts));
|
||||
|
||||
if (!array_key_exists($part, $node)) {
|
||||
$node[$part] = array();
|
||||
}
|
||||
|
||||
if (0 < count($tldParts)) {
|
||||
buildSubdomain($node[$part], $tldParts);
|
||||
}
|
||||
}
|
||||
|
||||
function writeNode($fp, $valueTree, $key = null, $indent = 0)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
fwrite($fp, "return ");
|
||||
|
||||
} else {
|
||||
fwrite($fp, str_repeat(' ', $indent) . "'$key' => ");
|
||||
}
|
||||
|
||||
if (0 == ($count = count($valueTree))) {
|
||||
fwrite($fp, 'true');
|
||||
} else {
|
||||
fwrite($fp, "array(\n");
|
||||
for ($keys = array_keys($valueTree), $i = 0; $i < $count; $i++) {
|
||||
writeNode($fp, $valueTree[$keys[$i]], $keys[$i], $indent + 1);
|
||||
if ($i + 1 != $count) {
|
||||
fwrite($fp, ",\n");
|
||||
} else {
|
||||
fwrite($fp, "\n");
|
||||
}
|
||||
}
|
||||
fwrite($fp, str_repeat(' ', $indent) . ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$request = new HTTP_Request2(LIST_URL);
|
||||
$response = $request->send();
|
||||
if (200 != $response->getStatus()) {
|
||||
throw new Exception("List download URL returned status: " .
|
||||
$response->getStatus() . ' ' . $response->getReasonPhrase());
|
||||
}
|
||||
$list = $response->getBody();
|
||||
if (false === strpos($list, 'The Original Code is the Public Suffix List.')) {
|
||||
throw new Exception("List download URL does not contain expected phrase");
|
||||
}
|
||||
if (!($fp = @fopen(OUTPUT_FILE, 'wt'))) {
|
||||
throw new Exception("Unable to open " . OUTPUT_FILE);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
|
||||
$tldTree = array();
|
||||
$license = true;
|
||||
|
||||
fwrite($fp, "<?php\n");
|
||||
|
||||
foreach (array_filter(array_map('trim', explode("\n", $list))) as $line) {
|
||||
if ('//' != substr($line, 0, 2)) {
|
||||
buildSubdomain($tldTree, explode('.', $line));
|
||||
|
||||
} elseif ($license) {
|
||||
fwrite($fp, $line . "\n");
|
||||
|
||||
if (0 === strpos($line, "// ***** END LICENSE BLOCK")) {
|
||||
$license = false;
|
||||
fwrite($fp, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeNode($fp, $tldTree);
|
||||
fwrite($fp, ";\n?>");
|
||||
fclose($fp);
|
||||
?>
|
4831
extlib/data/public-suffix-list.php
Normal file
4831
extlib/data/public-suffix-list.php
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user