Updating external libraries for net access

This commit is contained in:
Mikael Nordfeldth 2013-10-05 14:29:02 +02:00
parent ce37edc1b0
commit c51086b302
16 changed files with 7223 additions and 2240 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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
*/

View File

@ -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,14 +406,15 @@ 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');
}
@ -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;
}

View File

@ -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)

View File

@ -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
{
}
?>

View File

@ -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)

View File

@ -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);

View File

@ -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
*/

View 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']
);
}
}
}
?>

View 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;
}
}
?>

View File

@ -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
View 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;
}
}

View 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);
?>

File diff suppressed because it is too large Load Diff