updated-packages

This commit is contained in:
RafficMohammed
2023-01-08 00:13:22 +05:30
parent 3ff7df7487
commit da241bacb6
12659 changed files with 563377 additions and 510538 deletions

View File

@@ -0,0 +1 @@
always_populate_raw_post_data=-1

View File

@@ -0,0 +1,6 @@
<VirtualHost *:8081>
ProxyRequests On
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

View File

@@ -0,0 +1,21 @@
<VirtualHost *:80>
DocumentRoot %TRAVIS_BUILD_DIR%/test/Client/_files
<Directory "%TRAVIS_BUILD_DIR%/test/Client/_files/">
Options FollowSymLinks MultiViews ExecCGI
AllowOverride All
Require all granted
</Directory>
# Wire up Apache to use Travis CI's php-fpm.
<IfModule mod_fastcgi.c>
AddHandler php%PHP_VERSION%-fcgi .php
Action php%PHP_VERSION%-fcgi /php%PHP_VERSION%-fcgi
Alias /php%PHP_VERSION%-fcgi /usr/lib/cgi-bin/php%PHP_VERSION%-fcgi
FastCgiExternalServer /usr/lib/cgi-bin/php%PHP_VERSION%-fcgi -host 127.0.0.1:9000 -pass-header Authorization
<Directory /usr/lib/cgi-bin>
Require all granted
</Directory>
</IfModule>
</VirtualHost>

View File

@@ -2,6 +2,235 @@
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 2.11.2 - 2019-12-30
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#207](https://github.com/zendframework/zend-http/pull/207) fixes case sensitivity for SameSite directive.
## 2.11.1 - 2019-12-04
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#204](https://github.com/zendframework/zend-http/pull/204) fixes numerous header classes to cast field value to string (since `HeaderInterface::getFieldValue()` specifies a return value of a string).
- [#182](https://github.com/zendframework/zend-http/pull/182) fixes detecting base uri in Request. Now `argv` is used only for CLI request as a fallback to detect script filename.
## 2.11.0 - 2019-12-03
### Added
- [#175](https://github.com/zendframework/zend-http/pull/175) adds support for Content Security Policy Level 3 Header directives.
- [#200](https://github.com/zendframework/zend-http/pull/200) adds support for additional directives in Content Security Policy header:
- `block-all-mixed-content`,
- `require-sri-for`,
- `trusted-types`,
- `upgrade-insecure-requests`.
- [#177](https://github.com/zendframework/zend-http/pull/177) adds support for Feature Policy header.
- [#186](https://github.com/zendframework/zend-http/pull/186) adds support for SameSite directive in Set-Cookie header.
### Changed
- [#194](https://github.com/zendframework/zend-http/pull/194) changes range of valid HTTP status codes to 100-599 (inclusive).
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#200](https://github.com/zendframework/zend-http/pull/200) fixes support for directives without value in Content Security Policy header.
## 2.10.1 - 2019-12-02
### Added
- Nothing.
### Changed
- [#190](https://github.com/zendframework/zend-http/pull/190) changes `ContentSecurityPolicy` to allow multiple values. Before it was not possible to provide multiple headers of that type.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#184](https://github.com/zendframework/zend-http/pull/184) fixes responses for request through the proxy with `HTTP/1.1 200 Connection established` header.
- [#187](https://github.com/zendframework/zend-http/pull/187) fixes infinite recursion on invalid header. Now `InvalidArgumentException` exception is thrown.
- [#188](https://github.com/zendframework/zend-http/pull/188) fixes `Client::setCookies` method to properly handle array of `SetCookie` objects. Per [documentation](https://docs.zendframework.com/zend-http/client/cookies/#usage) it should be allowed.
- [#189](https://github.com/zendframework/zend-http/pull/189) fixes `Headers::toArray` method to properly handle headers of the same type. Behaviour was different depends how header has been attached (`addHeader` or `addHeaderLine` broken before).
- [#198](https://github.com/zendframework/zend-http/pull/198) fixes merging options in Curl adapter. It was not possible to override integer-key options (constants) set via constructor with method `setOptions`.
- [#198](https://github.com/zendframework/zend-http/pull/198) fixes allowed options type in `Proxy::setOptions`. `Traversable`, `array` or `Zend\Config` object is expected.
- [#198](https://github.com/zendframework/zend-http/pull/198) fixes various issues with `Proxy` adapter.
- [#199](https://github.com/zendframework/zend-http/pull/199) fixes saving resource to the file when streaming while client supports compression. Before, incorrectly, compressed resource was saved into the file.
## 2.10.0 - 2019-02-19
### Added
- [#173](https://github.com/zendframework/zend-http/pull/173) adds support for HTTP/2 requests and responses.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.9.1 - 2019-01-22
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#168](https://github.com/zendframework/zend-http/pull/168) fixes a problem when validating the connection timeout for the `Curl` and
`Socket` client adapters; it now correctly identifies both integer and string
integer values.
## 2.9.0 - 2019-01-08
### Added
- [#154](https://github.com/zendframework/zend-http/pull/154) adds the method `SetCookie::setEncodeValue()`. By default, Set-Cookie
values are passed through `urlencode()`; when a boolean `false` is provided to
this new method, the raw value will be used instead.
- [#166](https://github.com/zendframework/zend-http/pull/166) adds support for PHP 7.3.
### Changed
- [#154](https://github.com/zendframework/zend-http/pull/154) changes the behavior of `SetCookie::fromString()` slightly: if the parsed
cookie value is the same as the one passed through `urldecode()`, the
`SetCookie` header's `$encodeValue` property will be toggled off to ensure the
value is not encoded in subsequent serializations, thus retaining the
integrity of the value between usages.
- [#161](https://github.com/zendframework/zend-http/pull/161) changes how the Socket and Test adapters aggregate headers. Previously,
they would `ucfirst()` the header name; now, they correctly leave the header
names untouched, as header names should be considered case-insensitive.
- [#156](https://github.com/zendframework/zend-http/pull/156) changes how gzip and deflate decompression occur in responses, ensuring
that if the Content-Length header reports 0, no decompression is attempted,
and an empty string is returned.
### Deprecated
- Nothing.
### Removed
- [#166](https://github.com/zendframework/zend-http/pull/166) removes support for zend-stdlib v2 releases.
### Fixed
- Nothing.
## 2.8.3 - 2019-01-08
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#165](https://github.com/zendframework/zend-http/pull/165) fixes detection of the base URL when operating under a CLI environment.
- [#149](https://github.com/zendframework/zend-http/pull/149) provides fixes to `Client::setUri()` to ensure its status as a relative
or absolute URI is correctly memoized.
- [#162](https://github.com/zendframework/zend-http/pull/162) fixes a typo in an exception message raised within `Cookies::fromString()`.
- [#121](https://github.com/zendframework/zend-http/pull/121) adds detection for non-numeric connection timeout values as well as
integer casting to ensure the timeout is set properly in both the Curl and
Socket adapters.
## 2.8.2 - 2018-08-13
### Added

View File

@@ -1,4 +1,4 @@
Copyright (c) 2005-2018, Zend Technologies USA, Inc.
Copyright (c) 2005-2019, Zend Technologies USA, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

View File

@@ -11,5 +11,20 @@ This library **does not** support [PSR-7](http://www.php-fig.org/psr/psr-7), as
it predates that specification. For PSR-7 support, please see our
[Diactoros component](https://docs.zendframework.com/zend-diactoros/).
- File issues at https://github.com/zendframework/zend-http/issues
- Documentation is at https://docs.zendframework.com/zend-http/
## Installation
Run the following to install this library:
```bash
$ composer require zendframework/zend-http
```
## Documentation
Browse the documentation online at https://docs.zendframework.com/zend-http/
## Support
* [Issues](https://github.com/zendframework/zend-http/issues/)
* [Chat](https://zendframework-slack.herokuapp.com/)
* [Forum](https://discourse.zendframework.com/)

View File

@@ -20,7 +20,7 @@
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-loader": "^2.5.1",
"zendframework/zend-stdlib": "^3.1 || ^2.7.7",
"zendframework/zend-stdlib": "^3.2.1",
"zendframework/zend-uri": "^2.5.2",
"zendframework/zend-validator": "^2.10.1"
},
@@ -47,8 +47,8 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.8.x-dev",
"dev-develop": "2.9.x-dev"
"dev-master": "2.11.x-dev",
"dev-develop": "2.12.x-dev"
}
},
"scripts": {

View File

@@ -21,6 +21,7 @@ abstract class AbstractMessage extends Message
*/
const VERSION_10 = '1.0';
const VERSION_11 = '1.1';
const VERSION_2 = '2';
/**#@-*/
/**
@@ -34,16 +35,16 @@ abstract class AbstractMessage extends Message
protected $headers;
/**
* Set the HTTP version for this object, one of 1.0 or 1.1
* (AbstractMessage::VERSION_10, AbstractMessage::VERSION_11)
* Set the HTTP version for this object, one of 1.0, 1.1 or 2
* (AbstractMessage::VERSION_10, AbstractMessage::VERSION_11, AbstractMessage::VERSION_2)
*
* @param string $version (Must be 1.0 or 1.1)
* @return AbstractMessage
* @param string $version (Must be 1.0, 1.1 or 2)
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setVersion($version)
{
if ($version != self::VERSION_10 && $version != self::VERSION_11) {
if (! in_array($version, [self::VERSION_10, self::VERSION_11, self::VERSION_2])) {
throw new Exception\InvalidArgumentException(
'Not valid or not supported HTTP version: ' . $version
);
@@ -68,7 +69,7 @@ abstract class AbstractMessage extends Message
*
* @see getHeaders()
* @param Headers $headers
* @return AbstractMessage
* @return $this
*/
public function setHeaders(Headers $headers)
{

View File

@@ -11,6 +11,7 @@ use ArrayIterator;
use Traversable;
use Zend\Http\Client\Adapter\Curl;
use Zend\Http\Client\Adapter\Socket;
use Zend\Http\Header\SetCookie;
use Zend\Stdlib;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\ErrorHandler;
@@ -151,7 +152,7 @@ class Client implements Stdlib\DispatchableInterface
* Set configuration parameters for this HTTP client
*
* @param array|Traversable $options
* @return Client
* @return $this
* @throws Client\Exception\InvalidArgumentException
*/
public function setOptions($options = [])
@@ -183,7 +184,7 @@ class Client implements Stdlib\DispatchableInterface
* separated from ->request() to preserve logic and readability
*
* @param Client\Adapter\AdapterInterface|string $adapter
* @return Client
* @return $this
* @throws Client\Exception\InvalidArgumentException
*/
public function setAdapter($adapter)
@@ -211,7 +212,7 @@ class Client implements Stdlib\DispatchableInterface
/**
* Load the connection adapter
*
* @return Client\Adapter\AdapterInterface $adapter
* @return Client\Adapter\AdapterInterface
*/
public function getAdapter()
{
@@ -226,7 +227,7 @@ class Client implements Stdlib\DispatchableInterface
* Set request
*
* @param Request $request
* @return Client
* @return $this
*/
public function setRequest(Request $request)
{
@@ -252,7 +253,7 @@ class Client implements Stdlib\DispatchableInterface
* Set response
*
* @param Response $response
* @return Client
* @return $this
*/
public function setResponse(Response $response)
{
@@ -307,7 +308,7 @@ class Client implements Stdlib\DispatchableInterface
* Set Uri (to the request)
*
* @param string|Http $uri
* @return Client
* @return $this
*/
public function setUri($uri)
{
@@ -324,14 +325,18 @@ class Client implements Stdlib\DispatchableInterface
$this->clearAuth();
}
$uri = $this->getUri();
$user = $uri->getUser();
$password = $uri->getPassword();
// Set auth if username and password has been specified in the uri
if ($this->getUri()->getUser() && $this->getUri()->getPassword()) {
$this->setAuth($this->getUri()->getUser(), $this->getUri()->getPassword());
if ($user && $password) {
$this->setAuth($user, $password);
}
// We have no ports, set the defaults
if (! $this->getUri()->getPort()) {
$this->getUri()->setPort(($this->getUri()->getScheme() == 'https' ? 443 : 80));
if (! $uri->getPort() && $uri->isAbsolute()) {
$uri->setPort($uri->getScheme() === 'https' ? 443 : 80);
}
}
return $this;
@@ -351,7 +356,7 @@ class Client implements Stdlib\DispatchableInterface
* Set the HTTP method (to the request)
*
* @param string $method
* @return Client
* @return $this
*/
public function setMethod($method)
{
@@ -390,7 +395,7 @@ class Client implements Stdlib\DispatchableInterface
* Set the query string argument separator
*
* @param string $argSeparator
* @return Client
* @return $this
*/
public function setArgSeparator($argSeparator)
{
@@ -418,7 +423,7 @@ class Client implements Stdlib\DispatchableInterface
*
* @param string $encType
* @param string $boundary
* @return Client
* @return $this
*/
public function setEncType($encType, $boundary = null)
{
@@ -449,7 +454,7 @@ class Client implements Stdlib\DispatchableInterface
* Set raw body (for advanced use cases)
*
* @param string $body
* @return Client
* @return $this
*/
public function setRawBody($body)
{
@@ -461,7 +466,7 @@ class Client implements Stdlib\DispatchableInterface
* Set the POST parameters
*
* @param array $post
* @return Client
* @return $this
*/
public function setParameterPost(array $post)
{
@@ -473,7 +478,7 @@ class Client implements Stdlib\DispatchableInterface
* Set the GET parameters
*
* @param array $query
* @return Client
* @return $this
*/
public function setParameterGet(array $query)
{
@@ -486,7 +491,7 @@ class Client implements Stdlib\DispatchableInterface
*
* @param bool $clearCookies Also clear all valid cookies? (defaults to false)
* @param bool $clearAuth Also clear http authentication? (defaults to true)
* @return Client
* @return $this
*/
public function resetParameters($clearCookies = false /*, $clearAuth = true */)
{
@@ -554,7 +559,7 @@ class Client implements Stdlib\DispatchableInterface
* @param string $maxAge
* @param string $version
* @throws Exception\InvalidArgumentException
* @return Client
* @return $this
*/
public function addCookie(
$cookie,
@@ -599,16 +604,20 @@ class Client implements Stdlib\DispatchableInterface
/**
* Set an array of cookies
*
* @param array $cookies
* @param array|SetCookie[] $cookies Cookies as name=>value pairs or instances of SetCookie.
* @throws Exception\InvalidArgumentException
* @return Client
* @return $this
*/
public function setCookies($cookies)
{
if (is_array($cookies)) {
$this->clearCookies();
foreach ($cookies as $name => $value) {
$this->addCookie($name, $value);
if ($value instanceof SetCookie) {
$this->addCookie($value);
} else {
$this->addCookie($name, $value);
}
}
} else {
throw new Exception\InvalidArgumentException('Invalid cookies passed as parameter, it must be an array');
@@ -629,7 +638,7 @@ class Client implements Stdlib\DispatchableInterface
*
* @param Headers|array $headers
* @throws Exception\InvalidArgumentException
* @return Client
* @return $this
*/
public function setHeaders($headers)
{
@@ -684,7 +693,7 @@ class Client implements Stdlib\DispatchableInterface
* Set streaming for received data
*
* @param string|bool $streamfile Stream file, true for temp file, false/null for no streaming
* @return \Zend\Http\Client
* @return $this
*/
public function setStream($streamfile = true)
{
@@ -708,8 +717,8 @@ class Client implements Stdlib\DispatchableInterface
/**
* Create temporary stream
*
* @throws Exception\RuntimeException
* @return resource
* @throws Exception\RuntimeException
*/
protected function openTempStream()
{
@@ -744,7 +753,7 @@ class Client implements Stdlib\DispatchableInterface
* @param string $password
* @param string $type
* @throws Exception\InvalidArgumentException
* @return Client
* @return $this
*/
public function setAuth($user, $password, $type = self::AUTH_BASIC)
{
@@ -850,14 +859,13 @@ class Client implements Stdlib\DispatchableInterface
*/
public function dispatch(Stdlib\RequestInterface $request, Stdlib\ResponseInterface $response = null)
{
$response = $this->send($request);
return $response;
return $this->send($request);
}
/**
* Send HTTP request
*
* @param Request $request
* @param Request|null $request
* @return Response
* @throws Exception\RuntimeException
* @throws Client\Exception\RuntimeException
@@ -901,8 +909,8 @@ class Client implements Stdlib\DispatchableInterface
}
}
// If we have no ports, set the defaults
if (! $uri->getPort()) {
$uri->setPort($uri->getScheme() == 'https' ? 443 : 80);
if (! $uri->getPort() && $uri->isAbsolute()) {
$uri->setPort($uri->getScheme() === 'https' ? 443 : 80);
}
// method
@@ -1035,7 +1043,7 @@ class Client implements Stdlib\DispatchableInterface
/**
* Fully reset the HTTP client (auth, cookies, request, response, etc.)
*
* @return Client
* @return $this
*/
public function reset()
{
@@ -1063,7 +1071,7 @@ class Client implements Stdlib\DispatchableInterface
* @param string $data Data to send (if null, $filename is read and sent)
* @param string $ctype Content type to use (if $data is set and $ctype is
* null, will be application/octet-stream)
* @return Client
* @return $this
* @throws Exception\RuntimeException
*/
public function setFileUpload($filename, $formname, $data = null, $ctype = null)
@@ -1146,8 +1154,8 @@ class Client implements Stdlib\DispatchableInterface
*
* @param resource|string $body
* @param Http $uri
* @throws Exception\RuntimeException
* @return array
* @throws Exception\RuntimeException
*/
protected function prepareHeaders($body, $uri)
{
@@ -1176,7 +1184,7 @@ class Client implements Stdlib\DispatchableInterface
// Set the Accept-encoding header if not set - depending on whether
// zlib is available or not.
if (! $this->getRequest()->getHeaders()->has('Accept-Encoding')) {
if (function_exists('gzinflate')) {
if (empty($this->config['outputstream']) && function_exists('gzinflate')) {
$headers['Accept-Encoding'] = 'gzip, deflate';
} else {
$headers['Accept-Encoding'] = 'identity';
@@ -1491,7 +1499,5 @@ class Client implements Stdlib\DispatchableInterface
$type
));
}
return;
}
}

View File

@@ -101,7 +101,7 @@ class Curl implements HttpAdapter, StreamInterface
* Set the configuration array for the adapter
*
* @param array|Traversable $options
* @return Curl
* @return $this
* @throws AdapterException\InvalidArgumentException
*/
public function setOptions($options = [])
@@ -143,7 +143,7 @@ class Curl implements HttpAdapter, StreamInterface
break;
default:
if (is_array($v) && isset($this->config[$option]) && is_array($this->config[$option])) {
$v = ArrayUtils::merge($this->config[$option], $v);
$v = ArrayUtils::merge($this->config[$option], $v, true);
}
$this->config[$option] = $v;
break;
@@ -168,7 +168,7 @@ class Curl implements HttpAdapter, StreamInterface
*
* @param string|int $option
* @param mixed $value
* @return Curl
* @return $this
*/
public function setCurlOption($option, $value)
{
@@ -208,6 +208,18 @@ class Curl implements HttpAdapter, StreamInterface
} else {
$connectTimeout = null;
}
if ($connectTimeout !== null && ! is_numeric($connectTimeout)) {
throw new AdapterException\InvalidArgumentException(sprintf(
'integer or numeric string expected, got %s',
gettype($connectTimeout)
));
}
if ($connectTimeout !== null) {
$connectTimeout = (int) $connectTimeout;
}
if ($connectTimeout !== null) {
if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT_MS, $connectTimeout * 1000);
@@ -413,9 +425,7 @@ class Curl implements HttpAdapter, StreamInterface
* Make sure POSTFIELDS is set after $curlMethod is set:
* @link http://de2.php.net/manual/en/function.curl-setopt.php#81161
*/
if (in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true)) {
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $body);
} elseif ($curlMethod == CURLOPT_UPLOAD) {
if ($curlMethod == CURLOPT_UPLOAD) {
// this covers a PUT by file-handle:
// Make the setting of this options explicit (rather than setting it through the loop following a bit lower)
// to group common functionality together.
@@ -423,6 +433,8 @@ class Curl implements HttpAdapter, StreamInterface
curl_setopt($this->curl, CURLOPT_INFILESIZE, $this->config['curloptions'][CURLOPT_INFILESIZE]);
unset($this->config['curloptions'][CURLOPT_INFILE]);
unset($this->config['curloptions'][CURLOPT_INFILESIZE]);
} elseif (in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true)) {
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $body);
}
// set additional curl options
@@ -482,7 +494,7 @@ class Curl implements HttpAdapter, StreamInterface
// cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string:
$responseHeaders = preg_replace(
"/HTTP\/1.0\s*200\s*Connection\s*established\\r\\n\\r\\n/",
"/HTTP\/1.[01]\s*200\s*Connection\s*established\\r\\n\\r\\n/",
'',
$responseHeaders
);
@@ -541,7 +553,7 @@ class Curl implements HttpAdapter, StreamInterface
* Set output stream for the response
*
* @param resource $stream
* @return Curl
* @return $this
*/
public function setOutputStream($stream)
{

View File

@@ -7,9 +7,11 @@
namespace Zend\Http\Client\Adapter;
use Traversable;
use Zend\Http\Client;
use Zend\Http\Client\Adapter\Exception as AdapterException;
use Zend\Http\Response;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\ErrorHandler;
/**
@@ -60,6 +62,15 @@ class Proxy extends Socket
*/
public function setOptions($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
throw new AdapterException\InvalidArgumentException(
'Array or Zend\Config object expected, got ' . gettype($options)
);
}
//enforcing that the proxy keys are set in the form proxy_*
foreach ($options as $k => $v) {
if (preg_match('/^proxy[a-z]+/', $k)) {
@@ -93,6 +104,7 @@ class Proxy extends Socket
/* Url might require stream context even if proxy connection doesn't */
if ($secure) {
$this->config['sslusecontext'] = true;
$this->setSslCryptoMethod = false;
}
// Connect (a non-secure connection) to the proxy server
@@ -129,7 +141,10 @@ class Proxy extends Socket
$host = $this->config['proxy_host'];
$port = $this->config['proxy_port'];
if ($this->connectedTo[0] != sprintf('tcp://%s', $host) || $this->connectedTo[1] != $port) {
$isSecure = strtolower($uri->getScheme()) === 'https';
$connectedHost = ($isSecure ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
if ($this->connectedTo[1] !== $port || $this->connectedTo[0] !== $connectedHost) {
throw new AdapterException\RuntimeException(
'Trying to write but we are connected to the wrong proxy server'
);
@@ -145,7 +160,7 @@ class Proxy extends Socket
}
// if we are proxying HTTPS, preform CONNECT handshake with the proxy
if ($uri->getScheme() == 'https' && ! $this->negotiated) {
if ($isSecure && ! $this->negotiated) {
$this->connectHandshake($uri->getHost(), $uri->getPort(), $httpVer, $headers);
$this->negotiated = true;
}
@@ -153,16 +168,21 @@ class Proxy extends Socket
// Save request method for later
$this->method = $method;
// Build request headers
if ($this->negotiated) {
$path = $uri->getPath();
$query = $uri->getQuery();
$path .= $query ? '?' . $query : '';
$request = sprintf('%s %s HTTP/%s%s', $method, $path, $httpVer, "\r\n");
} else {
$request = sprintf('%s %s HTTP/%s%s', $method, $uri, $httpVer, "\r\n");
if ($uri->getUserInfo()) {
$headers['Authorization'] = 'Basic ' . base64_encode($uri->getUserInfo());
}
$path = $uri->getPath();
$query = $uri->getQuery();
$path .= $query ? '?' . $query : '';
if (! $this->negotiated) {
$path = $uri->getScheme() . '://' . $uri->getHost() . $path;
}
// Build request headers
$request = sprintf('%s %s HTTP/%s%s', $method, $path, $httpVer, "\r\n");
// Add all headers to the request string
foreach ($headers as $k => $v) {
if (is_string($k)) {
@@ -182,7 +202,7 @@ class Proxy extends Socket
ErrorHandler::start();
$test = fwrite($this->socket, $request);
$error = ErrorHandler::stop();
if (! $test) {
if ($test === false) {
throw new AdapterException\RuntimeException('Error writing request to proxy server', 0, $error);
}

View File

@@ -86,6 +86,11 @@ class Socket implements HttpAdapter, StreamInterface
*/
protected $context;
/**
* @var bool
*/
protected $setSslCryptoMethod = true;
/**
* Adapter constructor, currently empty. Config is set using setOptions()
*
@@ -138,7 +143,7 @@ class Socket implements HttpAdapter, StreamInterface
*
* @param mixed $context Stream context or array of context options
* @throws Exception\InvalidArgumentException
* @return Socket
* @return $this
*/
public function setStreamContext($context)
{
@@ -262,6 +267,14 @@ class Socket implements HttpAdapter, StreamInterface
} else {
$connectTimeout = $this->config['timeout'];
}
if ($connectTimeout !== null && ! is_numeric($connectTimeout)) {
throw new AdapterException\InvalidArgumentException(sprintf(
'integer or numeric string expected, got %s',
gettype($connectTimeout)
));
}
ErrorHandler::start();
$this->socket = stream_socket_client(
$host . ':' . $port,
@@ -293,47 +306,52 @@ class Socket implements HttpAdapter, StreamInterface
}
if ($secure || $this->config['sslusecontext']) {
if ($this->config['ssltransport'] && isset(static::$sslCryptoTypes[$this->config['ssltransport']])) {
$sslCryptoMethod = static::$sslCryptoTypes[$this->config['ssltransport']];
} else {
$sslCryptoMethod = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
}
if ($this->setSslCryptoMethod) {
if ($this->config['ssltransport']
&& isset(static::$sslCryptoTypes[$this->config['ssltransport']])
) {
$sslCryptoMethod = static::$sslCryptoTypes[$this->config['ssltransport']];
} else {
$sslCryptoMethod = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
}
ErrorHandler::start();
$test = stream_socket_enable_crypto($this->socket, true, $sslCryptoMethod);
$error = ErrorHandler::stop();
if (! $test || $error) {
// Error handling is kind of difficult when it comes to SSL
$errorString = '';
if (extension_loaded('openssl')) {
while (($sslError = openssl_error_string()) != false) {
$errorString .= sprintf('; SSL error: %s', $sslError);
ErrorHandler::start();
$test = stream_socket_enable_crypto($this->socket, true, $sslCryptoMethod);
$error = ErrorHandler::stop();
if (! $test || $error) {
// Error handling is kind of difficult when it comes to SSL
$errorString = '';
if (extension_loaded('openssl')) {
while (($sslError = openssl_error_string()) != false) {
$errorString .= sprintf('; SSL error: %s', $sslError);
}
}
}
$this->close();
$this->close();
if ((! $errorString) && $this->config['sslverifypeer']) {
// There's good chance our error is due to sslcapath not being properly set
if (! ($this->config['sslcafile'] || $this->config['sslcapath'])) {
$errorString = 'make sure the "sslcafile" or "sslcapath" option are properly set for the '
. 'environment.';
} elseif ($this->config['sslcafile'] && ! is_file($this->config['sslcafile'])) {
$errorString = 'make sure the "sslcafile" option points to a valid SSL certificate file';
} elseif ($this->config['sslcapath'] && ! is_dir($this->config['sslcapath'])) {
$errorString = 'make sure the "sslcapath" option points to a valid SSL certificate '
. 'directory';
if ((! $errorString) && $this->config['sslverifypeer']) {
// There's good chance our error is due to sslcapath not being properly set
if (! ($this->config['sslcafile'] || $this->config['sslcapath'])) {
$errorString = 'make sure the "sslcafile" or "sslcapath" option are properly set for '
. 'the environment.';
} elseif ($this->config['sslcafile'] && ! is_file($this->config['sslcafile'])) {
$errorString = 'make sure the "sslcafile" option points to a valid SSL certificate '
. 'file';
} elseif ($this->config['sslcapath'] && ! is_dir($this->config['sslcapath'])) {
$errorString = 'make sure the "sslcapath" option points to a valid SSL certificate '
. 'directory';
}
}
}
if ($errorString) {
$errorString = sprintf(': %s', $errorString);
}
if ($errorString) {
$errorString = sprintf(': %s', $errorString);
}
throw new AdapterException\RuntimeException(sprintf(
'Unable to enable crypto on TCP connection %s%s',
$host,
$errorString
), 0, $error);
throw new AdapterException\RuntimeException(sprintf(
'Unable to enable crypto on TCP connection %s%s',
$host,
$errorString
), 0, $error);
}
}
$host = $this->config['ssltransport'] . '://' . $host;
@@ -381,7 +399,7 @@ class Socket implements HttpAdapter, StreamInterface
$request = $method . ' ' . $path . ' HTTP/' . $httpVer . "\r\n";
foreach ($headers as $k => $v) {
if (is_string($k)) {
$v = ucfirst($k) . ': ' . $v;
$v = $k . ': ' . $v;
}
$request .= $v . "\r\n";
}

View File

@@ -132,7 +132,7 @@ class Test implements AdapterInterface
$request = $method . ' ' . $path . ' HTTP/' . $httpVer . "\r\n";
foreach ($headers as $k => $v) {
if (is_string($k)) {
$v = ucfirst($k) . ': ' . $v;
$v = $k . ': ' . $v;
}
$request .= $v . "\r\n";
}

View File

@@ -78,7 +78,7 @@ class Cookies extends Headers
{
throw new Exception\RuntimeException(
__CLASS__ . '::' . __FUNCTION__ . ' should not be used as a factory, use '
. __NAMESPACE__ . '\Headers::fromtString() instead.'
. __NAMESPACE__ . '\Headers::fromString() instead.'
);
}
@@ -338,7 +338,7 @@ class Cookies extends Headers
*
* @param Response $response HTTP Response object
* @param Uri\Uri|string $refUri The requested URI
* @return Cookies
* @return static
* @todo Add the $uri functionality.
*/
public static function fromResponse(Response $response, $refUri)
@@ -361,7 +361,7 @@ class Cookies extends Headers
/**
* Empties the cookieJar of any cookie
*
* @return Cookies
* @return $this
*/
public function reset()
{

View File

@@ -77,7 +77,7 @@ abstract class AbstractAccept implements HeaderInterface
* Factory method: parse Accept header string
*
* @param string $headerLine
* @return Accept
* @return static
*/
public static function fromString($headerLine)
{
@@ -242,7 +242,7 @@ abstract class AbstractAccept implements HeaderInterface
* @param int|float $priority
* @param array (optional) $params
* @throws Exception\InvalidArgumentException
* @return Accept
* @return $this
*/
protected function addType($type, $priority = 1, array $params = [])
{

View File

@@ -65,7 +65,7 @@ abstract class AbstractDate implements HeaderInterface
* Create date-based header from string
*
* @param string $headerLine
* @return AbstractDate
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
@@ -90,9 +90,7 @@ abstract class AbstractDate implements HeaderInterface
* Create date-based header from strtotime()-compatible string
*
* @param int|string $time
*
* @return self
*
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromTimeString($time)
@@ -104,9 +102,7 @@ abstract class AbstractDate implements HeaderInterface
* Create date-based header from Unix timestamp
*
* @param int $time
*
* @return self
*
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromTimestamp($time)
@@ -156,7 +152,7 @@ abstract class AbstractDate implements HeaderInterface
* Set the date for this header, this can be a string or an instance of \DateTime
*
* @param string|DateTime $date
* @return AbstractDate
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setDate($date)

View File

@@ -35,7 +35,7 @@ abstract class AbstractLocation implements HeaderInterface
* Create location-based header from string
*
* @param string $headerLine
* @return AbstractLocation
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
@@ -62,7 +62,7 @@ abstract class AbstractLocation implements HeaderInterface
* Set the URI/URL for this header, this can be a string or an instance of Zend\Uri\Http
*
* @param string|UriInterface $uri
* @return AbstractLocation
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setUri($uri)

View File

@@ -47,7 +47,7 @@ class Accept extends AbstractAccept
* @param string $type
* @param int|float $priority
* @param array $params
* @return Accept
* @return $this
*/
public function addMediaType($type, $priority = 1, array $params = [])
{

View File

@@ -38,7 +38,7 @@ abstract class AbstractFieldValuePart
* Set a Field Value Part this Field Value Part matched against.
*
* @param AbstractFieldValuePart $matchedAgainst
* @return AbstractFieldValuePart provides fluent interface
* @return $this
*/
public function setMatchedAgainst(AbstractFieldValuePart $matchedAgainst)
{

View File

@@ -43,7 +43,7 @@ class AcceptCharset extends AbstractAccept
*
* @param string $type
* @param int|float $priority
* @return Accept
* @return $this
*/
public function addCharset($type, $priority = 1)
{

View File

@@ -43,7 +43,7 @@ class AcceptEncoding extends AbstractAccept
*
* @param string $type
* @param int|float $priority
* @return Accept
* @return $this
*/
public function addEncoding($type, $priority = 1)
{

View File

@@ -43,7 +43,7 @@ class AcceptLanguage extends AbstractAccept
*
* @param string $type
* @param int|float $priority
* @return Accept
* @return $this
*/
public function addLanguage($type, $priority = 1)
{

View File

@@ -27,14 +27,12 @@ class AcceptRanges implements HeaderInterface
);
}
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($rangeUnit = null)
{
if ($rangeUnit) {
if ($rangeUnit !== null) {
$this->setRangeUnit($rangeUnit);
}
}
@@ -58,7 +56,7 @@ class AcceptRanges implements HeaderInterface
public function getRangeUnit()
{
return $this->rangeUnit;
return (string) $this->rangeUnit;
}
public function toString()

View File

@@ -25,7 +25,7 @@ class Age implements HeaderInterface
* Create Age header from string
*
* @param string $headerLine
* @return Age
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
@@ -37,14 +37,12 @@ class Age implements HeaderInterface
throw new Exception\InvalidArgumentException('Invalid header line for Age string: "' . $name . '"');
}
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($deltaSeconds = null)
{
if ($deltaSeconds) {
if ($deltaSeconds !== null) {
$this->setDeltaSeconds($deltaSeconds);
}
}
@@ -62,18 +60,18 @@ class Age implements HeaderInterface
/**
* Get header value (number of seconds)
*
* @return int
* @return string
*/
public function getFieldValue()
{
return $this->getDeltaSeconds();
return (string) $this->getDeltaSeconds();
}
/**
* Set number of seconds
*
* @param int $delta
* @return RetryAfter
* @return $this
*/
public function setDeltaSeconds($delta)
{

View File

@@ -39,7 +39,7 @@ class Allow implements HeaderInterface
* Create Allow header from header line
*
* @param string $headerLine
* @return Allow
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
@@ -102,7 +102,7 @@ class Allow implements HeaderInterface
* Allow methods or list of methods
*
* @param array|string $allowedMethods
* @return Allow
* @return $this
*/
public function allowMethods($allowedMethods)
{
@@ -124,7 +124,7 @@ class Allow implements HeaderInterface
* Disallow methods or list of methods
*
* @param array|string $disallowedMethods
* @return Allow
* @return $this
*/
public function disallowMethods($disallowedMethods)
{
@@ -146,7 +146,7 @@ class Allow implements HeaderInterface
* Convenience alias for @see disallowMethods()
*
* @param array|string $disallowedMethods
* @return Allow
* @return $this
*/
public function denyMethods($disallowedMethods)
{

View File

@@ -31,14 +31,12 @@ class AuthenticationInfo implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class AuthenticationInfo implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class Authorization implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class Authorization implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -30,7 +30,7 @@ class CacheControl implements HeaderInterface
*
* @param string $headerLine
* @throws Exception\InvalidArgumentException
* @return CacheControl
* @return static
*/
public static function fromString($headerLine)
{
@@ -83,7 +83,7 @@ class CacheControl implements HeaderInterface
*
* @param string $key
* @param string|bool $value
* @return CacheControl - provides the fluent interface
* @return $this
*/
public function addDirective($key, $value = true)
{
@@ -121,7 +121,7 @@ class CacheControl implements HeaderInterface
* Remove a directive
*
* @param string $key
* @return CacheControl - provides the fluent interface
* @return $this
*/
public function removeDirective($key)
{

View File

@@ -26,7 +26,7 @@ class Connection implements HeaderInterface
/**
* @param string $headerLine
* @return Connection
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
@@ -49,7 +49,7 @@ class Connection implements HeaderInterface
* Set Connection header to define persistent connection
*
* @param bool $flag
* @return Connection
* @return $this
*/
public function setPersistent($flag)
{
@@ -74,7 +74,7 @@ class Connection implements HeaderInterface
* RFC allows any token as value, 'close' and 'keep-alive' are commonly used
*
* @param string $value
* @return Connection
* @return $this
*/
public function setValue($value)
{

View File

@@ -31,14 +31,12 @@ class ContentDisposition implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class ContentDisposition implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -30,14 +30,12 @@ class ContentEncoding implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -50,7 +48,7 @@ class ContentEncoding implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class ContentLanguage implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class ContentLanguage implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,9 +31,7 @@ class ContentLength implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
@@ -51,7 +49,7 @@ class ContentLength implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class ContentMD5 implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class ContentMD5 implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class ContentRange implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class ContentRange implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -8,11 +8,11 @@
namespace Zend\Http\Header;
/**
* Content Security Policy 1.0 Header
* Content Security Policy Level 3 Header
*
* @link http://www.w3.org/TR/CSP/
*/
class ContentSecurityPolicy implements HeaderInterface
class ContentSecurityPolicy implements MultipleHeaderInterface
{
/**
* Valid directive names
@@ -21,17 +21,44 @@ class ContentSecurityPolicy implements HeaderInterface
*/
protected $validDirectiveNames = [
// As per http://www.w3.org/TR/CSP/#directives
'default-src',
'script-src',
'object-src',
'style-src',
'img-src',
'media-src',
'frame-src',
'font-src',
// Fetch directives
'child-src',
'connect-src',
'default-src',
'font-src',
'frame-src',
'img-src',
'manifest-src',
'media-src',
'object-src',
'prefetch-src',
'script-src',
'script-src-elem',
'script-src-attr',
'style-src',
'style-src-elem',
'style-src-attr',
'worker-src',
// Document directives
'base-uri',
'plugin-types',
'sandbox',
// Navigation directives
'form-action',
'frame-ancestors',
'navigate-to',
// Reporting directives
'report-uri',
'report-to',
// Other directives
'block-all-mixed-content',
'require-sri-for',
'trusted-types',
'upgrade-insecure-requests',
];
/**
@@ -58,7 +85,7 @@ class ContentSecurityPolicy implements HeaderInterface
*
* @param string $name The directive name.
* @param array $sources The source list.
* @return self
* @return $this
* @throws Exception\InvalidArgumentException If the name is not a valid directive name.
*/
public function setDirective($name, array $sources)
@@ -70,6 +97,21 @@ class ContentSecurityPolicy implements HeaderInterface
(string) $name
));
}
if ($name === 'block-all-mixed-content'
|| $name === 'upgrade-insecure-requests'
) {
if ($sources) {
throw new Exception\InvalidArgumentException(sprintf(
'Received value for %s directive; none expected',
$name
));
}
$this->directives[$name] = '';
return $this;
}
if (empty($sources)) {
if ('report-uri' === $name) {
if (isset($this->directives[$name])) {
@@ -77,13 +119,14 @@ class ContentSecurityPolicy implements HeaderInterface
}
return $this;
}
$this->directives[$name] = "'none'";
return $this;
}
array_walk($sources, [__NAMESPACE__ . '\HeaderValue', 'assertValid']);
$this->directives[$name] = implode(' ', $sources);
return $this;
}
@@ -91,7 +134,7 @@ class ContentSecurityPolicy implements HeaderInterface
* Create Content Security Policy header from a given header line
*
* @param string $headerLine The header line to parse.
* @return self
* @return static
* @throws Exception\InvalidArgumentException If the name field in the given header line does not match.
*/
public static function fromString($headerLine)
@@ -112,9 +155,12 @@ class ContentSecurityPolicy implements HeaderInterface
foreach ($tokens as $token) {
$token = trim($token);
if ($token) {
list($directiveName, $directiveValue) = explode(' ', $token, 2);
list($directiveName, $directiveValue) = array_pad(explode(' ', $token, 2), 2, null);
if (! isset($header->directives[$directiveName])) {
$header->setDirective($directiveName, [$directiveValue]);
$header->setDirective(
$directiveName,
$directiveValue === null ? [] : [$directiveValue]
);
}
}
}
@@ -142,7 +188,7 @@ class ContentSecurityPolicy implements HeaderInterface
foreach ($this->directives as $name => $value) {
$directives[] = sprintf('%s %s;', $name, $value);
}
return implode(' ', $directives);
return str_replace(' ;', ';', implode(' ', $directives));
}
/**
@@ -154,4 +200,20 @@ class ContentSecurityPolicy implements HeaderInterface
{
return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue());
}
public function toStringMultipleHeaders(array $headers)
{
$strings = [$this->toString()];
foreach ($headers as $header) {
if (! $header instanceof ContentSecurityPolicy) {
throw new Exception\RuntimeException(
'The ContentSecurityPolicy multiple header implementation can only'
. ' accept an array of ContentSecurityPolicy headers'
);
}
$strings[] = $header->toString();
}
return implode("\r\n", $strings) . "\r\n";
}
}

View File

@@ -31,14 +31,12 @@ class ContentTransferEncoding implements HeaderInterface
}
// @todo implementation details
$header = new static(strtolower($value));
return $header;
return new static(strtolower($value));
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class ContentTransferEncoding implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -34,7 +34,7 @@ class ContentType implements HeaderInterface
* Factory method: create an object from a string representation
*
* @param string $headerLine
* @return self
* @return static
*/
public static function fromString($headerLine)
{
@@ -69,7 +69,7 @@ class ContentType implements HeaderInterface
public function __construct($value = null, $mediaType = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -146,7 +146,7 @@ class ContentType implements HeaderInterface
public function getFieldValue()
{
if (null !== $this->value) {
return $this->value;
return (string) $this->value;
}
return $this->assembleValue();
}
@@ -155,7 +155,7 @@ class ContentType implements HeaderInterface
* Set the media type
*
* @param string $mediaType
* @return self
* @return $this
*/
public function setMediaType($mediaType)
{
@@ -172,14 +172,14 @@ class ContentType implements HeaderInterface
*/
public function getMediaType()
{
return $this->mediaType;
return (string) $this->mediaType;
}
/**
* Set additional content-type parameters
*
* @param array $parameters
* @return self
* @return $this
*/
public function setParameters(array $parameters)
{
@@ -206,7 +206,7 @@ class ContentType implements HeaderInterface
* Set the content-type character set encoding
*
* @param string $charset
* @return self
* @return $this
*/
public function setCharset($charset)
{

View File

@@ -75,12 +75,20 @@ class Cookie extends ArrayObject implements HeaderInterface
parent::__construct($array, ArrayObject::ARRAY_AS_PROPS);
}
/**
* @param bool $encodeValue
*
* @return $this
*/
public function setEncodeValue($encodeValue)
{
$this->encodeValue = (bool) $encodeValue;
return $this;
}
/**
* @return bool
*/
public function getEncodeValue()
{
return $this->encodeValue;

View File

@@ -28,14 +28,12 @@ class Etag implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Etag implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Expect implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Expect implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -0,0 +1,184 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2019 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Feature Policy (based on Editors Draft, 28 November 2019)
*
* @link https://w3c.github.io/webappsec-feature-policy/
*/
class FeaturePolicy implements HeaderInterface
{
/**
* Valid directive names
*
* @var string[]
*
* @see https://github.com/w3c/webappsec-feature-policy/blob/master/features.md
*/
protected $validDirectiveNames = [
// Standardized Features
'accelerometer',
'ambient-light-sensor',
'autoplay',
'battery',
'camera',
'display-capture',
'document-domain',
'fullscreen',
'execution-while-not-rendered',
'execution-while-out-of-viewport',
'gyroscope',
'magnetometer',
'microphone',
'midi',
'payment',
'picture-in-picture',
'sync-xhr',
'usb',
'wake-lock',
'xr',
// Proposed Features
'encrypted-media',
'geolocation',
'speaker',
// Experimental Features
'document-write',
'font-display-late-swap',
'layout-animations',
'loading-frame-default-eager',
'loading-image-default-eager',
'legacy-image-formats',
'oversized-images',
'sync-script',
'unoptimized-lossy-images',
'unoptimized-lossless-images',
'unsized-media',
'vertical-scroll',
'serial',
];
/**
* The directives defined for this policy
*
* @var array
*/
protected $directives = [];
/**
* Get the list of defined directives
*
* @return array
*/
public function getDirectives()
{
return $this->directives;
}
/**
* Sets the directive to consist of the source list
*
* @param string $name The directive name.
* @param string[] $sources The source list.
* @return $this
* @throws Exception\InvalidArgumentException If the name is not a valid directive name.
*/
public function setDirective($name, array $sources)
{
if (! in_array($name, $this->validDirectiveNames, true)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a valid directive name; received "%s"',
__METHOD__,
(string) $name
));
}
if (empty($sources)) {
$this->directives[$name] = "'none'";
return $this;
}
array_walk($sources, [__NAMESPACE__ . '\HeaderValue', 'assertValid']);
$this->directives[$name] = implode(' ', $sources);
return $this;
}
/**
* Create Feature Policy header from a given header line
*
* @param string $headerLine The header line to parse.
* @return static
* @throws Exception\InvalidArgumentException If the name field in the given header line does not match.
*/
public static function fromString($headerLine)
{
$header = new static();
$headerName = $header->getFieldName();
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// Ensure the proper header name
if (strcasecmp($name, $headerName) !== 0) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for %s string: "%s"',
$headerName,
$name
));
}
// As per https://w3c.github.io/webappsec-feature-policy/#algo-parse-policy-directive
$tokens = explode(';', $value);
foreach ($tokens as $token) {
$token = trim($token);
if ($token) {
list($directiveName, $directiveValue) = array_pad(explode(' ', $token, 2), 2, null);
if (! isset($header->directives[$directiveName])) {
$header->setDirective(
$directiveName,
$directiveValue === null ? [] : [$directiveValue]
);
}
}
}
return $header;
}
/**
* Get the header name
*
* @return string
*/
public function getFieldName()
{
return 'Feature-Policy';
}
/**
* Get the header value
*
* @return string
*/
public function getFieldValue()
{
$directives = [];
foreach ($this->directives as $name => $value) {
$directives[] = sprintf('%s %s;', $name, $value);
}
return implode(' ', $directives);
}
/**
* Return the header as a string
*
* @return string
*/
public function toString()
{
return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue());
}
}

View File

@@ -28,14 +28,12 @@ class From implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class From implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -25,15 +25,14 @@ class GenericHeader implements HeaderInterface
/**
* Factory to generate a header object from a string
*
* @static
* @param string $headerLine
* @return GenericHeader
* @return static
*/
public static function fromString($headerLine)
{
list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
$header = new static($fieldName, $fieldValue);
return $header;
return new static($fieldName, $fieldValue);
}
/**
@@ -80,7 +79,7 @@ class GenericHeader implements HeaderInterface
* Set header field name
*
* @param string $fieldName
* @return GenericHeader
* @return $this
* @throws Exception\InvalidArgumentException If the name does not match with RFC 2616 format.
*/
public function setFieldName($fieldName)
@@ -122,7 +121,7 @@ class GenericHeader implements HeaderInterface
* Set header field value
*
* @param string $fieldValue
* @return GenericHeader
* @return $this
*/
public function setFieldValue($fieldValue)
{

View File

@@ -16,7 +16,7 @@ interface HeaderInterface
* Factory to generate a header object from a string
*
* @param string $headerLine
* @return self
* @return static
* @throws Exception\InvalidArgumentException If the header does not match RFC 2616 definition.
* @see http://tools.ietf.org/html/rfc2616#section-4.2
*/

View File

@@ -28,14 +28,12 @@ class Host implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Host implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class IfMatch implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class IfMatch implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class IfNoneMatch implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class IfNoneMatch implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class IfRange implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class IfRange implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class KeepAlive implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class KeepAlive implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class MaxForwards implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class MaxForwards implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -42,7 +42,7 @@ class Origin implements HeaderInterface
*/
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -55,7 +55,7 @@ class Origin implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Pragma implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Pragma implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class ProxyAuthenticate implements MultipleHeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class ProxyAuthenticate implements MultipleHeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class ProxyAuthorization implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class ProxyAuthorization implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Range implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Range implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -21,7 +21,7 @@ class Referer extends AbstractLocation
* according to RFC Referer URI should not have fragment
*
* @param string|HttpUri $uri
* @return Referer
* @return $this
*/
public function setUri($uri)
{

View File

@@ -28,14 +28,12 @@ class Refresh implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Refresh implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -26,7 +26,7 @@ class RetryAfter extends AbstractDate
* Create Retry-After header from string
*
* @param string $headerLine
* @return RetryAfter
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
@@ -55,7 +55,7 @@ class RetryAfter extends AbstractDate
* Set number of seconds
*
* @param int $delta
* @return RetryAfter
* @return $this
*/
public function setDeltaSeconds($delta)
{

View File

@@ -1,7 +1,7 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2019 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
@@ -28,14 +28,12 @@ class Server implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Server implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -1,7 +1,7 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2019 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
@@ -10,6 +10,11 @@ namespace Zend\Http\Header;
use DateTime;
use Zend\Uri\UriFactory;
use function array_key_exists;
use function gettype;
use function is_scalar;
use function strtolower;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.ietf.org/rfc/rfc2109.txt
@@ -17,6 +22,33 @@ use Zend\Uri\UriFactory;
*/
class SetCookie implements MultipleHeaderInterface
{
/**
* Cookie will not be sent for any cross-domain requests whatsoever.
* Even if the user simply navigates to the target site with a regular link, the cookie will not be sent.
*/
const SAME_SITE_STRICT = 'Strict';
/**
* Cookie will not be passed for any cross-domain requests unless it's a regular link that navigates user
* to the target site.
* Other requests methods (such as POST and PUT) and XHR requests will not contain this cookie.
*/
const SAME_SITE_LAX = 'Lax';
/**
* Cookie will be sent with same-site and cross-site requests.
*/
const SAME_SITE_NONE = 'None';
/**
* @internal
*/
const SAME_SITE_ALLOWED_VALUES = [
'strict' => self::SAME_SITE_STRICT,
'lax' => self::SAME_SITE_LAX,
'none' => self::SAME_SITE_NONE,
];
/**
* Cookie name
*
@@ -85,6 +117,16 @@ class SetCookie implements MultipleHeaderInterface
*/
protected $httponly;
/**
* @var string|null
*/
protected $sameSite;
/**
* @var bool
*/
protected $encodeValue = true;
/**
* @static
* @throws Exception\InvalidArgumentException
@@ -99,6 +141,7 @@ class SetCookie implements MultipleHeaderInterface
if ($setCookieProcessor === null) {
$setCookieClass = get_called_class();
$setCookieProcessor = function ($headerLine) use ($setCookieClass) {
/** @var SetCookie $header */
$header = new $setCookieClass();
$keyValuePairs = preg_split('#;\s*#', $headerLine);
@@ -115,6 +158,11 @@ class SetCookie implements MultipleHeaderInterface
if ($header->getName() === null) {
$header->setName($headerKey);
$header->setValue(urldecode($headerValue));
// set no encode value if raw and encoded values are the same
if (urldecode($headerValue) === $headerValue) {
$header->setEncodeValue(false);
}
continue;
}
@@ -141,6 +189,9 @@ class SetCookie implements MultipleHeaderInterface
case 'maxage':
$header->setMaxAge($headerValue);
break;
case 'samesite':
$header->setSameSite($headerValue);
break;
default:
// Intentionally omitted
}
@@ -179,15 +230,16 @@ class SetCookie implements MultipleHeaderInterface
*
* @todo Add validation of each one of the parameters (legal domain, etc.)
*
* @param string $name
* @param string $value
* @param int|string|DateTime $expires
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httponly
* @param string $maxAge
* @param int $version
* @param string|null $name
* @param string|null $value
* @param int|string|DateTime|null $expires
* @param string|null $path
* @param string|null $domain
* @param bool $secure
* @param bool $httponly
* @param int|null $maxAge
* @param int|null $version
* @param string|null $sameSite
*/
public function __construct(
$name = null,
@@ -198,7 +250,8 @@ class SetCookie implements MultipleHeaderInterface
$secure = false,
$httponly = false,
$maxAge = null,
$version = null
$version = null,
$sameSite = null
) {
$this->type = 'Cookie';
@@ -210,7 +263,24 @@ class SetCookie implements MultipleHeaderInterface
->setExpires($expires)
->setPath($path)
->setSecure($secure)
->setHttpOnly($httponly);
->setHttpOnly($httponly)
->setSameSite($sameSite);
}
/**
* @return bool
*/
public function getEncodeValue()
{
return $this->encodeValue;
}
/**
* @param bool $encodeValue
*/
public function setEncodeValue($encodeValue)
{
$this->encodeValue = (bool) $encodeValue;
}
/**
@@ -231,7 +301,7 @@ class SetCookie implements MultipleHeaderInterface
return '';
}
$value = urlencode($this->getValue());
$value = $this->encodeValue ? urlencode($this->getValue()) : $this->getValue();
if ($this->hasQuoteFieldValue()) {
$value = '"' . $value . '"';
}
@@ -271,13 +341,18 @@ class SetCookie implements MultipleHeaderInterface
$fieldValue .= '; HttpOnly';
}
$sameSite = $this->getSameSite();
if ($sameSite !== null && array_key_exists(strtolower($sameSite), self::SAME_SITE_ALLOWED_VALUES)) {
$fieldValue .= '; SameSite=' . $sameSite;
}
return $fieldValue;
}
/**
* @param string $name
* @param string|null $name
* @return $this
* @throws Exception\InvalidArgumentException
* @return SetCookie
*/
public function setName($name)
{
@@ -287,7 +362,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @return string
* @return string|null
*/
public function getName()
{
@@ -295,8 +370,8 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @param string $value
* @return SetCookie
* @param string|null $value
* @return $this
*/
public function setValue($value)
{
@@ -305,7 +380,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @return string
* @return string|null
*/
public function getValue()
{
@@ -313,11 +388,9 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* Set version
*
* @param int $version
* @param int|null $version
* @return $this
* @throws Exception\InvalidArgumentException
* @return SetCookie
*/
public function setVersion($version)
{
@@ -329,9 +402,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* Get version
*
* @return int
* @return int|null
*/
public function getVersion()
{
@@ -339,10 +410,8 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* Set Max-Age
*
* @param int $maxAge
* @return SetCookie
* @param int $maxAge
* @return $this
*/
public function setMaxAge($maxAge)
{
@@ -355,9 +424,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* Get Max-Age
*
* @return int
* @return int|null
*/
public function getMaxAge()
{
@@ -365,12 +432,8 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* Set Expires
*
* @param int|string|DateTime $expires
*
* @return self
*
* @param int|string|DateTime|null $expires
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setExpires($expires)
@@ -408,13 +471,13 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @param bool $inSeconds
* @return int|string
* @param bool $inSeconds
* @return int|string|null
*/
public function getExpires($inSeconds = false)
{
if ($this->expires === null) {
return;
return null;
}
if ($inSeconds) {
return $this->expires;
@@ -423,8 +486,8 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @param string $domain
* @return SetCookie
* @param string|null $domain
* @return $this
*/
public function setDomain($domain)
{
@@ -434,7 +497,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @return string
* @return string|null
*/
public function getDomain()
{
@@ -442,8 +505,8 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @param string $path
* @return SetCookie
* @param string|null $path
* @return $this
*/
public function setPath($path)
{
@@ -453,7 +516,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @return string
* @return string|null
*/
public function getPath()
{
@@ -461,8 +524,8 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @param bool $secure
* @return SetCookie
* @param bool|null $secure
* @return $this
*/
public function setSecure($secure)
{
@@ -477,7 +540,7 @@ class SetCookie implements MultipleHeaderInterface
* Set whether the value for this cookie should be quoted
*
* @param bool $quotedValue
* @return SetCookie
* @return $this
*/
public function setQuoteFieldValue($quotedValue)
{
@@ -486,7 +549,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @return bool
* @return bool|null
*/
public function isSecure()
{
@@ -494,8 +557,8 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @param bool $httponly
* @return SetCookie
* @param bool|null $httponly
* @return $this
*/
public function setHttponly($httponly)
{
@@ -507,7 +570,7 @@ class SetCookie implements MultipleHeaderInterface
}
/**
* @return bool
* @return bool|null
*/
public function isHttponly()
{
@@ -519,7 +582,7 @@ class SetCookie implements MultipleHeaderInterface
*
* Always returns false if the cookie is a session cookie (has no expiry time)
*
* @param int $now Timestamp to consider as "now"
* @param int|null $now Timestamp to consider as "now"
* @return bool
*/
public function isExpired($now = null)
@@ -545,6 +608,35 @@ class SetCookie implements MultipleHeaderInterface
return ($this->expires === null);
}
/**
* @return string|null
*/
public function getSameSite()
{
return $this->sameSite;
}
/**
* @param string|null $sameSite
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setSameSite($sameSite)
{
if ($sameSite === null) {
$this->sameSite = null;
return $this;
}
if (! array_key_exists(strtolower($sameSite), self::SAME_SITE_ALLOWED_VALUES)) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid value provided for SameSite directive: "%s"; expected one of: Strict, Lax or None',
is_scalar($sameSite) ? $sameSite : gettype($sameSite)
));
}
$this->sameSite = self::SAME_SITE_ALLOWED_VALUES[strtolower($sameSite)];
return $this;
}
/**
* Check whether the value for this cookie should be quoted
*
@@ -555,6 +647,12 @@ class SetCookie implements MultipleHeaderInterface
return $this->quoteFieldValue;
}
/**
* @param string $requestDomain
* @param string $path
* @param bool $isSecure
* @return bool
*/
public function isValidForRequest($requestDomain, $path, $isSecure = false)
{
if ($this->getDomain() && (strrpos($requestDomain, $this->getDomain()) === false)) {
@@ -577,7 +675,7 @@ class SetCookie implements MultipleHeaderInterface
*
* @param string|\Zend\Uri\Uri $uri URI to check against (secure, domain, path)
* @param bool $matchSessionCookies Whether to send session cookies
* @param int $now Override the current time when checking for expiry time
* @param int|null $now Override the current time when checking for expiry time
* @return bool
* @throws Exception\InvalidArgumentException If URI does not have HTTP or HTTPS scheme.
*/
@@ -624,7 +722,6 @@ class SetCookie implements MultipleHeaderInterface
*
* @param string $cookieDomain
* @param string $host
*
* @return bool
*/
public static function matchCookieDomain($cookieDomain, $host)
@@ -650,11 +747,19 @@ class SetCookie implements MultipleHeaderInterface
return (strpos($path, $cookiePath) === 0);
}
/**
* @return string
*/
public function toString()
{
return 'Set-Cookie: ' . $this->getFieldValue();
}
/**
* @param array $headers
* @return string
* @throws Exception\RuntimeException
*/
public function toStringMultipleHeaders(array $headers)
{
$headerLine = $this->toString();

View File

@@ -28,14 +28,12 @@ class TE implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class TE implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Trailer implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Trailer implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -30,14 +30,12 @@ class TransferEncoding implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -50,7 +48,7 @@ class TransferEncoding implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Upgrade implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Upgrade implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class UserAgent implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class UserAgent implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Vary implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Vary implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Via implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Via implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -31,14 +31,12 @@ class WWWAuthenticate implements MultipleHeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -51,7 +49,7 @@ class WWWAuthenticate implements MultipleHeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -28,14 +28,12 @@ class Warning implements HeaderInterface
}
// @todo implementation details
$header = new static($value);
return $header;
return new static($value);
}
public function __construct($value = null)
{
if ($value) {
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
@@ -48,7 +46,7 @@ class Warning implements HeaderInterface
public function getFieldValue()
{
return $this->value;
return (string) $this->value;
}
public function toString()

View File

@@ -36,6 +36,7 @@ class HeaderLoader extends PluginClassLoader
'contentlocation' => Header\ContentLocation::class,
'contentmd5' => Header\ContentMD5::class,
'contentrange' => Header\ContentRange::class,
'contentsecuritypolicy' => Header\ContentSecurityPolicy::class,
'contenttransferencoding' => Header\ContentTransferEncoding::class,
'contenttype' => Header\ContentType::class,
'cookie' => Header\Cookie::class,
@@ -43,6 +44,7 @@ class HeaderLoader extends PluginClassLoader
'etag' => Header\Etag::class,
'expect' => Header\Expect::class,
'expires' => Header\Expires::class,
'featurepolicy' => Header\FeaturePolicy::class,
'from' => Header\From::class,
'host' => Header\Host::class,
'ifmatch' => Header\IfMatch::class,

View File

@@ -46,7 +46,7 @@ class Headers implements Countable, Iterator
* will be lazy loaded)
*
* @param string $string
* @return Headers
* @return static
* @throws Exception\RuntimeException
*/
public static function fromString($string)
@@ -109,8 +109,8 @@ class Headers implements Countable, Iterator
/**
* Set an alternate implementation for the PluginClassLoader
*
* @param \Zend\Loader\PluginClassLocator $pluginClassLoader
* @return Headers
* @param PluginClassLocator $pluginClassLoader
* @return $this
*/
public function setPluginClassLoader(PluginClassLocator $pluginClassLoader)
{
@@ -137,7 +137,7 @@ class Headers implements Countable, Iterator
* Expects an array (or Traversable object) of type/value pairs.
*
* @param array|Traversable $headers
* @return Headers
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function addHeaders($headers)
@@ -177,7 +177,7 @@ class Headers implements Countable, Iterator
* @throws Exception\InvalidArgumentException
* @param string $headerFieldNameOrLine
* @param string $fieldValue optional
* @return Headers
* @return $this
*/
public function addHeaderLine($headerFieldNameOrLine, $fieldValue = null)
{
@@ -194,7 +194,7 @@ class Headers implements Countable, Iterator
$headerName = $headerFieldNameOrLine;
$headerKey = static::createKey($headerFieldNameOrLine);
if (is_array($fieldValue)) {
$fieldValue = implode(', ', $fieldValue);
$fieldValue = implode('; ', $fieldValue);
}
$line = $headerFieldNameOrLine . ': ' . $fieldValue;
}
@@ -209,7 +209,7 @@ class Headers implements Countable, Iterator
* Add a Header to this container, for raw values @see addHeaderLine() and addHeaders()
*
* @param Header\HeaderInterface $header
* @return Headers
* @return $this
*/
public function addHeader(Header\HeaderInterface $header)
{
@@ -261,7 +261,7 @@ class Headers implements Countable, Iterator
*
* Removes all headers from queue
*
* @return Headers
* @return $this
*/
public function clearHeaders()
{
@@ -420,21 +420,19 @@ class Headers implements Countable, Iterator
{
$headers = [];
/* @var $header Header\HeaderInterface */
foreach ($this->headers as $header) {
foreach ($this->headers as $index => $header) {
if (is_array($header)) {
$header = $this->lazyLoadHeader($index);
}
if ($header instanceof Header\MultipleHeaderInterface) {
$name = $header->getFieldName();
if (! isset($headers[$name])) {
$headers[$name] = [];
}
$headers[$name][] = $header->getFieldValue();
} elseif ($header instanceof Header\HeaderInterface) {
$headers[$header->getFieldName()] = $header->getFieldValue();
} else {
$matches = null;
preg_match('/^(?P<name>[^()><@,;:\"\\/\[\]?=}{ \t]+):\s*(?P<value>.*)$/', $header['line'], $matches);
if ($matches) {
$headers[$matches['name']] = $matches['value'];
}
$headers[$header->getFieldName()] = $header->getFieldValue();
}
}
return $headers;
@@ -455,7 +453,7 @@ class Headers implements Countable, Iterator
/**
* @param $index
* @param bool $isGeneric
* @param bool $isGeneric If true, there is no need to parse $index and call the ClassLoader.
* @return mixed|void
*/
protected function lazyLoadHeader($index, $isGeneric = false)
@@ -472,6 +470,12 @@ class Headers implements Countable, Iterator
try {
$headers = $class::fromString($current['line']);
} catch (Exception\InvalidArgumentException $exception) {
// Generic Header should throw an exception if it fails
if ($isGeneric) {
throw $exception;
}
// Retry one more time with GenericHeader
return $this->lazyLoadHeader($index, true);
}
if (is_array($headers)) {

View File

@@ -45,7 +45,7 @@ class RemoteAddress
* at session read, so this is the only way to switch setting.
*
* @param bool $useProxy Whether to check also proxied IP addresses.
* @return RemoteAddress
* @return $this
*/
public function setUseProxy($useProxy = true)
{
@@ -67,7 +67,7 @@ class RemoteAddress
* Set list of trusted proxy addresses
*
* @param array $trustedProxies
* @return RemoteAddress
* @return $this
*/
public function setTrustedProxies(array $trustedProxies)
{
@@ -79,7 +79,7 @@ class RemoteAddress
* Set the header to introspect for proxy IPs
*
* @param string $header
* @return RemoteAddress
* @return $this
*/
public function setProxyHeader($header = 'X-Forwarded-For')
{

View File

@@ -107,7 +107,7 @@ class Request extends HttpRequest
* Instantiate and set cookies.
*
* @param $cookie
* @return Request
* @return $this
*/
public function setCookies($cookie)
{
@@ -119,7 +119,7 @@ class Request extends HttpRequest
* Set the request URI.
*
* @param string $requestUri
* @return self
* @return $this
*/
public function setRequestUri($requestUri)
{
@@ -144,7 +144,7 @@ class Request extends HttpRequest
* Set the base URL.
*
* @param string $baseUrl
* @return self
* @return $this
*/
public function setBaseUrl($baseUrl)
{
@@ -169,7 +169,7 @@ class Request extends HttpRequest
* Set the base path.
*
* @param string $basePath
* @return self
* @return $this
*/
public function setBasePath($basePath)
{
@@ -196,7 +196,7 @@ class Request extends HttpRequest
* (this is NOT the primary API for value setting, for that see getServer())
*
* @param ParametersInterface $server
* @return Request
* @return $this
*/
public function setServer(ParametersInterface $server)
{
@@ -266,8 +266,9 @@ class Request extends HttpRequest
$port = null;
// Set the host
if ($this->getHeaders()->get('host')) {
$host = $this->getHeaders()->get('host')->getFieldValue();
$headerHost = $this->getHeaders()->get('host');
if ($headerHost) {
$host = $headerHost->getFieldValue();
// works for regname, IPv4 & IPv6
if (preg_match('|\:(\d+)$|', $host, $matches)) {
@@ -351,7 +352,7 @@ class Request extends HttpRequest
* (this is NOT the primary API for value setting, for that see env())
*
* @param ParametersInterface $env
* @return Request
* @return $this
*/
public function setEnv(ParametersInterface $env)
{
@@ -489,6 +490,15 @@ class Request extends HttpRequest
// Backtrack up the SCRIPT_FILENAME to find the portion
// matching PHP_SELF.
// Only for CLI requests argv[0] contains script filename
// @see https://www.php.net/manual/en/reserved.variables.server.php
if (PHP_SAPI === 'cli') {
$argv = $this->getServer()->get('argv', []);
if (isset($argv[0]) && is_string($argv[0]) && $argv[0] !== '' && strpos($filename, $argv[0]) === 0) {
$filename = substr($filename, strlen($argv[0]));
}
}
$baseUrl = '/';
$basename = basename($filename);
if ($basename) {

View File

@@ -76,7 +76,7 @@ class Response extends HttpResponse
/**
* Send HTTP headers
*
* @return Response
* @return $this
*/
public function sendHeaders()
{
@@ -103,7 +103,7 @@ class Response extends HttpResponse
/**
* Send content
*
* @return Response
* @return $this
*/
public function sendContent()
{
@@ -119,7 +119,7 @@ class Response extends HttpResponse
/**
* Send HTTP response
*
* @return Response
* @return $this
*/
public function send()
{

View File

@@ -71,7 +71,7 @@ class Request extends AbstractMessage implements RequestInterface
* @param string $string
* @param bool $allowCustomMethods
* @throws Exception\InvalidArgumentException
* @return Request
* @return static
*/
public static function fromString($string, $allowCustomMethods = true)
{
@@ -166,7 +166,7 @@ class Request extends AbstractMessage implements RequestInterface
* Set the method for this request
*
* @param string $method
* @return Request
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setMethod($method)
@@ -194,7 +194,7 @@ class Request extends AbstractMessage implements RequestInterface
*
* @throws Exception\InvalidArgumentException
* @param string|HttpUri $uri
* @return Request
* @return $this
*/
public function setUri($uri)
{
@@ -248,8 +248,8 @@ class Request extends AbstractMessage implements RequestInterface
* Provide an alternate Parameter Container implementation for query parameters in this object,
* (this is NOT the primary API for value setting, for that see getQuery())
*
* @param \Zend\Stdlib\ParametersInterface $query
* @return Request
* @param ParametersInterface $query
* @return $this
*/
public function setQuery(ParametersInterface $query)
{
@@ -260,9 +260,9 @@ class Request extends AbstractMessage implements RequestInterface
/**
* Return the parameter container responsible for query parameters or a single query parameter
*
* @param string|null $name Parameter name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the parameter is missing.
* @return \Zend\Stdlib\ParametersInterface|mixed
* @param string|null $name Parameter name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the parameter is missing.
* @return ParametersInterface|mixed
*/
public function getQuery($name = null, $default = null)
{
@@ -281,8 +281,8 @@ class Request extends AbstractMessage implements RequestInterface
* Provide an alternate Parameter Container implementation for post parameters in this object,
* (this is NOT the primary API for value setting, for that see getPost())
*
* @param \Zend\Stdlib\ParametersInterface $post
* @return Request
* @param ParametersInterface $post
* @return $this
*/
public function setPost(ParametersInterface $post)
{
@@ -293,9 +293,9 @@ class Request extends AbstractMessage implements RequestInterface
/**
* Return the parameter container responsible for post parameters or a single post parameter.
*
* @param string|null $name Parameter name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the parameter is missing.
* @return \Zend\Stdlib\ParametersInterface|mixed
* @param string|null $name Parameter name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the parameter is missing.
* @return ParametersInterface|mixed
*/
public function getPost($name = null, $default = null)
{
@@ -326,7 +326,7 @@ class Request extends AbstractMessage implements RequestInterface
* (this is NOT the primary API for value setting, for that see getFiles())
*
* @param ParametersInterface $files
* @return Request
* @return $this
*/
public function setFiles(ParametersInterface $files)
{
@@ -337,8 +337,8 @@ class Request extends AbstractMessage implements RequestInterface
/**
* Return the parameter container responsible for file parameters or a single file.
*
* @param string|null $name Parameter name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the parameter is missing.
* @param string|null $name Parameter name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the parameter is missing.
* @return ParametersInterface|mixed
*/
public function getFiles($name = null, $default = null)
@@ -358,8 +358,8 @@ class Request extends AbstractMessage implements RequestInterface
* Return the header container responsible for headers or all headers of a certain name/type
*
* @see \Zend\Http\Headers::get()
* @param string|null $name Header name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the requested header is missing.
* @param string|null $name Header name to retrieve, or null to get the whole container.
* @param mixed|null $default Default value to use when the requested header is missing.
* @return \Zend\Http\Headers|bool|\Zend\Http\Header\HeaderInterface|\ArrayIterator
*/
public function getHeaders($name = null, $default = false)

View File

@@ -88,6 +88,16 @@ class Response extends AbstractMessage implements ResponseInterface
const STATUS_CODE_599 = 599;
/**#@-*/
/**
* @internal
*/
const MIN_STATUS_CODE_VALUE = 100;
/**
* @internal
*/
const MAX_STATUS_CODE_VALUE = 599;
/**
* @var array Recommended Reason Phrases
*/
@@ -177,7 +187,7 @@ class Response extends AbstractMessage implements ResponseInterface
* Populate object from string
*
* @param string $string
* @return self
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($string)
@@ -249,7 +259,7 @@ class Response extends AbstractMessage implements ResponseInterface
*/
protected function parseStatusLine($line)
{
$regex = '/^HTTP\/(?P<version>1\.[01]) (?P<status>\d{3})(?:[ ]+(?P<reason>.*))?$/';
$regex = '/^HTTP\/(?P<version>1\.[01]|2) (?P<status>\d{3})(?:[ ]+(?P<reason>.*))?$/';
$matches = [];
if (! preg_match($regex, $line, $matches)) {
throw new Exception\InvalidArgumentException(
@@ -275,16 +285,20 @@ class Response extends AbstractMessage implements ResponseInterface
*
* @param int $code
* @throws Exception\InvalidArgumentException
* @return self
* @return $this
*/
public function setStatusCode($code)
{
$const = get_class($this) . '::STATUS_CODE_' . $code;
if (! is_numeric($code) || ! defined($const)) {
$code = is_scalar($code) ? $code : gettype($code);
if (! is_numeric($code)
|| is_float($code)
|| $code < static::MIN_STATUS_CODE_VALUE
|| $code > static::MAX_STATUS_CODE_VALUE
) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid status code provided: "%s"',
$code
'Invalid status code "%s"; must be an integer between %d and %d, inclusive',
is_scalar($code) ? $code : gettype($code),
static::MIN_STATUS_CODE_VALUE,
static::MAX_STATUS_CODE_VALUE
));
}
@@ -306,7 +320,7 @@ class Response extends AbstractMessage implements ResponseInterface
*
* @param int $code
* @throws Exception\InvalidArgumentException
* @return self
* @return $this
*/
public function setCustomStatusCode($code)
{
@@ -325,7 +339,7 @@ class Response extends AbstractMessage implements ResponseInterface
* Assign status code
*
* @param int $code
* @return self
* @return $this
*/
protected function saveStatusCode($code)
{
@@ -336,7 +350,7 @@ class Response extends AbstractMessage implements ResponseInterface
/**
* @param string $reasonPhrase
* @return self
* @return $this
*/
public function setReasonPhrase($reasonPhrase)
{
@@ -564,6 +578,13 @@ class Response extends AbstractMessage implements ResponseInterface
);
}
if ($body === ''
|| ($this->getHeaders()->has('content-length')
&& (int) $this->getHeaders()->get('content-length')->getFieldValue() === 0)
) {
return '';
}
ErrorHandler::start();
$return = gzinflate(substr($body, 10));
$test = ErrorHandler::stop();
@@ -594,6 +615,11 @@ class Response extends AbstractMessage implements ResponseInterface
);
}
if ($this->getHeaders()->has('content-length')
&& 0 === (int) $this->getHeaders()->get('content-length')->getFieldValue()) {
return '';
}
/**
* Some servers (IIS ?) send a broken deflate response, without the
* RFC-required zlib header.

View File

@@ -87,7 +87,7 @@ class Stream extends Response
* Set the response stream
*
* @param resource $stream
* @return Stream
* @return $this
*/
public function setStream($stream)
{
@@ -129,7 +129,7 @@ class Stream extends Response
* Set file name associated with the stream
*
* @param string $streamName Name to set
* @return Stream
* @return $this
*/
public function setStreamName($streamName)
{
@@ -142,7 +142,7 @@ class Stream extends Response
*
* @param string $responseString
* @param resource $stream
* @return Stream
* @return $this
* @throws Exception\InvalidArgumentException
* @throws Exception\OutOfRangeException
*/