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

@@ -2,6 +2,28 @@
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 2.6.1 - 2019-09-05
### Added
- [#32](https://github.com/zendframework/zend-escaper/pull/32) adds support for PHP 7.3.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.6.0 - 2018-04-25
### 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

@@ -9,5 +9,20 @@ of which one is commonly misapplied. Thus, the zend-escaper component was writte
It offers developers a way to escape output and defend from XSS and related
vulnerabilities by introducing contextual escaping based on peer-reviewed rules.
- File issues at https://github.com/zendframework/zend-escaper/issues
- Documentation is at https://docs.zendframework.com/zend-escaper/
## Installation
Run the following to install this library:
```bash
$ composer require zendframework/zend-escaper
```
## Documentation
Browse the documentation online at https://docs.zendframework.com/zend-escaper/
## Support
* [Issues](https://github.com/zendframework/zend-escaper/issues/)
* [Chat](https://zendframework-slack.herokuapp.com/)
* [Forum](https://discourse.zendframework.com/)

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

View File

@@ -2,6 +2,118 @@
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 3.1.2 - 2019-10-09
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#46](https://github.com/zendframework/zend-json/pull/46) changes
curly braces in array and string offset access to square brackets
in order to prevent issues under the upcoming PHP 7.4 release.
- [#37](https://github.com/zendframework/zend-json/pull/37) fixes
output of `\Zend\Json::prettyPrint` to not remove spaces after
commas in value.
## 3.1.1 - 2019-06-18
### Added
- [#44](https://github.com/zendframework/zend-json/pull/44) adds support for PHP 7.3.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 3.1.0 - 2018-01-04
### Added
- [#35](https://github.com/zendframework/zend-json/pull/35) and
[#39](https://github.com/zendframework/zend-json/pull/39) add support for PHP
7.1 and PHP 7.2.
### Deprecated
- Nothing.
### Removed
- [#35](https://github.com/zendframework/zend-json/pull/35) removes support for
PHP 5.5.
- [#35](https://github.com/zendframework/zend-json/pull/35) removes support for
HHVM.
### Fixed
- [#38](https://github.com/zendframework/zend-json/pull/38) provides a fix to
`Json::prettyPrint()` to ensure that empty arrays and objects are printed
without newlines.
- [#38](https://github.com/zendframework/zend-json/pull/38) provides a fix to
`Json::prettyPrint()` to remove additional newlines preceding a closing
bracket.
## 3.0.0 - 2016-03-31
### Added
- [#21](https://github.com/zendframework/zend-json/pull/21) adds documentation
and publishes it to https://zendframework.github.io/zend-json/
### Deprecated
- Nothing.
### Removed
- [#20](https://github.com/zendframework/zend-json/pull/20) removes the
`Zend\Json\Server` subcomponent, which has been extracted to
[zend-json-server](https://zendframework.github.io/zend-json-server/).
If you use that functionality, install the new component.
- [#21](https://github.com/zendframework/zend-json/pull/21) removes the
`Zend\Json\Json::fromXml()` functionality, which has been extracted to
[zend-xml2json](https://zendframework.github.io/zend-xml2json/). If you used
this functionality, you will need to install the new package, and rewrite
calls to `Zend\Json\Json::fromXml()` to `Zend\Xml2Json\Xml2Json::fromXml()`.
- [#20](https://github.com/zendframework/zend-json/pull/20) and
[#21](https://github.com/zendframework/zend-json/pull/21) removes dependencies
on zendframework/zendxml, zendframework/zend-stdlib,
zendframework/zend-server, and zendframework-zend-http, due to the above
listed component extractions.
### Fixed
- Nothing.
## 2.6.1 - 2016-02-04
### Added

View File

@@ -1,229 +0,0 @@
# CONTRIBUTING
## RESOURCES
If you wish to contribute to Zend Framework, please be sure to
read/subscribe to the following resources:
- [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards)
- [Contributor's Guide](http://framework.zend.com/participate/contributor-guide)
- ZF Contributor's mailing list:
Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html
Subscribe: zf-contributors-subscribe@lists.zend.com
- ZF Contributor's IRC channel:
#zftalk.dev on Freenode.net
If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-json/issues/new).
## Reporting Potential Security Issues
If you have encountered a potential security vulnerability, please **DO NOT** report it on the public
issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead.
We will work with you to verify the vulnerability and patch it as soon as possible.
When reporting issues, please provide the following information:
- Component(s) affected
- A description indicating how to reproduce the issue
- A summary of the security vulnerability and impact
We request that you contact us via the email address above and give the project
contributors a chance to resolve the vulnerability and issue a new release prior
to any public exposure; this helps protect users and provides them with a chance
to upgrade and/or update in order to protect their applications.
For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc).
## RUNNING TESTS
> ### Note: testing versions prior to 2.4
>
> This component originates with Zend Framework 2. During the lifetime of ZF2,
> testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no
> changes were necessary. However, due to the migration, tests may not run on
> versions < 2.4. As such, you may need to change the PHPUnit dependency if
> attempting a fix on such a version.
To run tests:
- Clone the repository:
```console
$ git clone git@github.com:zendframework/zend-json.git
$ cd
```
- Install dependencies via composer:
```console
$ curl -sS https://getcomposer.org/installer | php --
$ ./composer.phar install
```
If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/
- Run the tests via `phpunit` and the provided PHPUnit config, like in this example:
```console
$ ./vendor/bin/phpunit
```
You can turn on conditional tests with the phpunit.xml file.
To do so:
- Copy `phpunit.xml.dist` file to `phpunit.xml`
- Edit `phpunit.xml` to enable any specific functionality you
want to test, as well as to provide test values to utilize.
## Running Coding Standards Checks
This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding
standards checks, and provides configuration for our selected checks.
`php-cs-fixer` is installed by default via Composer.
To run checks only:
```console
$ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs
```
To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run`
flag:
```console
$ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs
```
If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure
they pass, and make sure you add and commit the changes after verification.
## Recommended Workflow for Contributions
Your first step is to establish a public repository from which we can
pull your work into the master repository. We recommend using
[GitHub](https://github.com), as that is where the component is already hosted.
1. Setup a [GitHub account](http://github.com/), if you haven't yet
2. Fork the repository (http://github.com/zendframework/zend-json)
3. Clone the canonical repository locally and enter it.
```console
$ git clone git://github.com:zendframework/zend-json.git
$ cd zend-json
```
4. Add a remote to your fork; substitute your GitHub username in the command
below.
```console
$ git remote add {username} git@github.com:{username}/zend-json.git
$ git fetch {username}
```
### Keeping Up-to-Date
Periodically, you should update your fork or personal repository to
match the canonical ZF repository. Assuming you have setup your local repository
per the instructions above, you can do the following:
```console
$ git checkout master
$ git fetch origin
$ git rebase origin/master
# OPTIONALLY, to keep your remote up-to-date -
$ git push {username} master:master
```
If you're tracking other branches -- for example, the "develop" branch, where
new feature development occurs -- you'll want to do the same operations for that
branch; simply substitute "develop" for "master".
### Working on a patch
We recommend you do each new feature or bugfix in a new branch. This simplifies
the task of code review as well as the task of merging your changes into the
canonical repository.
A typical workflow will then consist of the following:
1. Create a new local branch based off either your master or develop branch.
2. Switch to your new local branch. (This step can be combined with the
previous step with the use of `git checkout -b`.)
3. Do some work, commit, repeat as necessary.
4. Push the local branch to your remote repository.
5. Send a pull request.
The mechanics of this process are actually quite trivial. Below, we will
create a branch for fixing an issue in the tracker.
```console
$ git checkout -b hotfix/9295
Switched to a new branch 'hotfix/9295'
```
... do some work ...
```console
$ git commit
```
... write your log message ...
```console
$ git push {username} hotfix/9295:hotfix/9295
Counting objects: 38, done.
Delta compression using up to 2 threads.
Compression objects: 100% (18/18), done.
Writing objects: 100% (20/20), 8.19KiB, done.
Total 20 (delta 12), reused 0 (delta 0)
To ssh://git@github.com/{username}/zend-json.git
b5583aa..4f51698 HEAD -> master
```
To send a pull request, you have two options.
If using GitHub, you can do the pull request from there. Navigate to
your repository, select the branch you just created, and then select the
"Pull Request" button in the upper right. Select the user/organization
"zendframework" as the recipient.
If using your own repository - or even if using GitHub - you can use `git
format-patch` to create a patchset for us to apply; in fact, this is
**recommended** for security-related patches. If you use `format-patch`, please
send the patches as attachments to:
- zf-devteam@zend.com for patches without security implications
- zf-security@zend.com for security patches
#### What branch to issue the pull request against?
Which branch should you issue a pull request against?
- For fixes against the stable release, issue the pull request against the
"master" branch.
- For new features, or fixes that introduce new elements to the public API (such
as new public methods or properties), issue the pull request against the
"develop" branch.
### Branch Cleanup
As you might imagine, if you are a frequent contributor, you'll start to
get a ton of branches both locally and on your remote.
Once you know that your changes have been accepted to the master
repository, we suggest doing some cleanup of these branches.
- Local branch cleanup
```console
$ git branch -d <branchname>
```
- Remote branch removal
```console
$ git push {username} :<branchname>
```

View File

@@ -1,16 +1,15 @@
Copyright (c) 2005-2015, 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,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name of Zend Technologies USA, Inc. nor the names of its
contributors may be used to endorse or promote products derived from this

View File

@@ -1,12 +1,27 @@
# zend-json
[![Build Status](https://secure.travis-ci.org/zendframework/zend-json.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-json)
[![Coverage Status](https://coveralls.io/repos/zendframework/zend-json/badge.svg?branch=master)](https://coveralls.io/r/zendframework/zend-json?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-json/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-json?branch=master)
`Zend\Json` provides convenience methods for serializing native PHP to JSON and
decoding JSON to native PHP. For more information on JSON, visit the JSON
[project site](http://www.json.org/).
- File issues at https://github.com/zendframework/zend-json/issues
- Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-json
## Installation
Run the following to install this library:
```bash
$ composer require zendframework/zend-json
```
## Documentation
Browse the documentation online at https://docs.zendframework.com/zend-json/
## Support
* [Issues](https://github.com/zendframework/zend-json/issues/)
* [Chat](https://zendframework-slack.herokuapp.com/)
* [Forum](https://discourse.zendframework.com/)

View File

@@ -3,32 +3,29 @@
"description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP",
"license": "BSD-3-Clause",
"keywords": [
"zf2",
"zf",
"zendframework",
"json"
],
"homepage": "https://github.com/zendframework/zend-json",
"extra": {
"branch-alias": {
"dev-master": "2.6-dev",
"dev-develop": "2.7-dev"
}
"support": {
"docs": "https://docs.zendframework.com/zend-json/",
"issues": "https://github.com/zendframework/zend-json/issues",
"source": "https://github.com/zendframework/zend-json",
"rss": "https://github.com/zendframework/zend-json/releases.atom",
"chat": "https://zendframework-slack.herokuapp.com",
"forum": "https://discourse.zendframework.com/c/questions/components"
},
"require": {
"php": "^5.5 || ^7.0"
"php": "^5.6 || ^7.0"
},
"require-dev": {
"zendframework/zend-http": "^2.5.4",
"zendframework/zend-server": "^2.6.1",
"zendframework/zend-stdlib": "^2.5 || ^3.0",
"zendframework/zendxml": "^1.0.2",
"fabpot/php-cs-fixer": "1.7.*",
"phpunit/PHPUnit": "~4.0"
"phpunit/phpunit": "^5.7.23 || ^6.4.3",
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-stdlib": "^2.7.7 || ^3.1"
},
"suggest": {
"zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server",
"zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server",
"zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses",
"zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage"
"zendframework/zend-json-server": "For implementing JSON-RPC servers",
"zendframework/zend-xml2json": "For converting XML documents to JSON"
},
"autoload": {
"psr-4": {
@@ -39,5 +36,24 @@
"psr-4": {
"ZendTest\\Json\\": "test/"
}
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "3.1.x-dev",
"dev-develop": "3.2.x-dev"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
}
}

View File

@@ -1,29 +0,0 @@
# Basic Usage
Usage of `Zend\Json` involves using the two public static methods available:
`Zend\Json\Json::encode()` and `Zend\Json\Json::decode()`.
```php
// Retrieve a value:
$phpNative = Zend\Json\Json::decode($encodedValue);
// Encode it to return to the client:
$json = Zend\Json\Json::encode($phpNative);
```
## Pretty-printing JSON
Sometimes, it may be hard to explore *JSON* data generated by `Zend\Json\Json::encode()`, since it
has no spacing or indentation. In order to make it easier, `Zend\Json\Json` allows you to
pretty-print *JSON* data in the human-readable format with `Zend\Json\Json::prettyPrint()`.
```php
// Encode it to return to the client:
$json = Zend\Json\Json::encode($phpNative);
if ($debug) {
echo Zend\Json\Json::prettyPrint($json, array("indent" => " "));
}
```
Second optional argument of `Zend\Json\Json::prettyPrint()` is an option array. Option `indent`
allows to set indentation string - by default it's a single tab character.

View File

@@ -1,16 +0,0 @@
# Introduction
`Zend\Json` provides convenience methods for serializing native *PHP* to *JSON* and decoding *JSON*
to native *PHP*. For more information on *JSON*, [visit the JSON project
site](http://www.json.org/).
*JSON*, JavaScript Object Notation, can be used for data interchange between JavaScript and other
languages. Since *JSON* can be directly evaluated by JavaScript, it is a more efficient and
lightweight format than *XML* for exchanging data with JavaScript clients.
In addition, `Zend\Json` provides a useful way to convert any arbitrary *XML* formatted string into
a *JSON* formatted string. This built-in feature will enable *PHP* developers to transform the
enterprise data encoded in *XML* format into *JSON* format before sending it to browser-based Ajax
client applications. It provides an easy way to do dynamic data conversion on the server-side code
thereby avoiding unnecessary *XML* parsing in the browser-side applications. It offers a nice
utility function that results in easier application-specific data processing techniques.

View File

@@ -1,101 +0,0 @@
# Advanced Usage
## JSON Objects
When encoding *PHP* objects as *JSON*, all public properties of that object will be encoded in a
*JSON* object.
*JSON* does not allow object references, so care should be taken not to encode objects with
recursive references. If you have issues with recursion, `Zend\Json\Json::encode()` and
`Zend\Json\Encoder::encode()` allow an optional second parameter to check for recursion; if an
object is serialized twice, an exception will be thrown.
Decoding *JSON* objects poses an additional difficulty, however, since JavaScript objects correspond
most closely to *PHP*'s associative array. Some suggest that a class identifier should be passed,
and an object instance of that class should be created and populated with the key/value pairs of the
*JSON* object; others feel this could pose a substantial security risk.
By default, `Zend\Json\Json` will decode *JSON* objects as `stdClass` objects. However, if you
desire an associative array returned, you can specify this:
```php
// Decode JSON objects as PHP array
$phpNative = Zend\Json\Json::decode($encodedValue, Zend\Json\Json::TYPE_ARRAY);
```
Any objects thus decoded are returned as associative arrays with keys and values corresponding to
the key/value pairs in the *JSON* notation.
The recommendation of Zend Framework is that the individual developer should decide how to decode
*JSON* objects. If an object of a specified type should be created, it can be created in the
developer code and populated with the values decoded using `Zend\Json`.
## Encoding PHP objects
If you are encoding *PHP* objects by default the encoding mechanism can only access public
properties of these objects. When a method `toJson()` is implemented on an object to encode,
`Zend\Json\Json` calls this method and expects the object to return a *JSON* representation of its
internal state.
`Zend\Json\Json` can encode PHP objects recursively but does not do so by default. This can be
enabled by passing `true` as a second argument to `Zend\Json\Json::encode()`.
```php
// Encode PHP object recursively
$jsonObject = Zend\Json\Json::encode($data, true);
```
When doing recursive encoding of objects, as JSON does not support cycles, an
`Zend\Json\Exception\RecursionException` will be thrown. If you wish, you can silence these
exceptions by passing the `silenceCyclicalExceptions` option:
```php
$jsonObject = Zend\Json\Json::encode(
$data,
true,
array('silenceCyclicalExceptions' => true)
);
```
## Internal Encoder/Decoder
`Zend\Json` has two different modes depending if ext/json is enabled in your *PHP* installation or
not. If ext/json is installed by default `json_encode()` and `json_decode()` functions are used for
encoding and decoding *JSON*. If ext/json is not installed a Zend Framework implementation in *PHP*
code is used for en-/decoding. This is considerably slower than using the *PHP* extension, but
behaves exactly the same.
Still sometimes you might want to use the internal encoder/decoder even if you have ext/json
installed. You can achieve this by calling:
```php
Zend\Json\Json::$useBuiltinEncoderDecoder = true;
```
## JSON Expressions
JavaScript makes heavy use of anonymous function callbacks, which can be saved within *JSON* object
variables. Still they only work if not returned inside double quotes, which `Zend\Json` naturally
does. With the Expression support for `Zend\Json` support you can encode *JSON* objects with valid
JavaScript callbacks. This works for both `json_encode()` or the internal encoder.
A JavaScript callback is represented using the `Zend\Json\Expr` object. It implements the value
object pattern and is immutable. You can set the JavaScript expression as the first constructor
argument. By default `Zend\Json\Json::encode` does not encode JavaScript callbacks, you have to pass
the option `enableJsonExprFinder` and set it to `TRUE` into the `encode` function. If enabled the
expression support works for all nested expressions in large object structures. A usage example
would look like:
```php
$data = array(
'onClick' => new Zend\Json\Expr('function() {'
. 'alert("I am a valid JavaScript callback '
. 'created by Zend\Json"); }'),
'other' => 'no expression',
);
$jsonObjectWithExpression = Zend\Json\Json::encode(
$data,
false,
array('enableJsonExprFinder' => true)
);
```

View File

@@ -1,368 +0,0 @@
# Zend\\Json\\Server - JSON-RPC server
## Introduction
`Zend\Json\Server` is a [JSON-RPC](http://groups.google.com/group/json-rpc/) server implementation.
It supports both the [JSON-RPC version 1 specification](http://json-rpc.org/wiki/specification) as
well as the [version 2 specification](http://www.jsonrpc.org/specification); additionally, it
provides a *PHP* implementation of the [Service Mapping Description (SMD)
specification](http://www.jsonrpc.org/specification) for providing service metadata to service
consumers.
JSON-RPC is a lightweight Remote Procedure Call protocol that utilizes *JSON* for its messaging
envelopes. This JSON-RPC implementation follows *PHP*'s
[SoapServer](http://www.php.net/manual/en/class.soapserver.php) *API*. This means, in a typical
situation, you will simply:
- Instantiate the server object
- Attach one or more functions and/or classes/objects to the server object
- handle() the request
`Zend\Json\Server` utilizes \[Zend\\Server\\Reflection\](zend.server.reflection) to perform
reflection on any attached classes or functions, and uses that information to build both the SMD and
enforce method call signatures. As such, it is imperative that any attached functions and/or class
methods have full *PHP* docblocks documenting, minimally:
- All parameters and their expected variable types
- The return value variable type
`Zend\Json\Server` listens for POST requests only at this time; fortunately, most JSON-RPC client
implementations in the wild at the time of this writing will only POST requests as it is. This makes
it simple to utilize the same server end point to both handle requests as well as to deliver the
service SMD, as is shown in the next example.
## Basic Usage
First, let's define a class we wish to expose via the JSON-RPC server. We'll call the class
'Calculator', and define methods for 'add', 'subtract', 'multiply', and 'divide':
```php
/**
* Calculator - sample class to expose via JSON-RPC
*/
class Calculator
{
/**
* Return sum of two variables
*
* @param int $x
* @param int $y
* @return int
*/
public function add($x, $y)
{
return $x + $y;
}
/**
* Return difference of two variables
*
* @param int $x
* @param int $y
* @return int
*/
public function subtract($x, $y)
{
return $x - $y;
}
/**
* Return product of two variables
*
* @param int $x
* @param int $y
* @return int
*/
public function multiply($x, $y)
{
return $x * $y;
}
/**
* Return the division of two variables
*
* @param int $x
* @param int $y
* @return float
*/
public function divide($x, $y)
{
return $x / $y;
}
}
```
Note that each method has a docblock with entries indicating each parameter and its type, as well as
an entry for the return value. This is **absolutely critical** when utilizing `Zend\Json\Server` or
any other server component in Zend Framework, for that matter.
Now we'll create a script to handle the requests:
```php
$server = new Zend\Json\Server\Server();
// Indicate what functionality is available:
$server->setClass('Calculator');
// Handle the request:
$server->handle();
```
However, this will not address the issue of returning an SMD so that the JSON-RPC client can
autodiscover methods. That can be accomplished by determining the *HTTP* request method, and then
specifying some server metadata:
```php
$server = new Zend\Json\Server\Server();
$server->setClass('Calculator');
if ('GET' == $_SERVER['REQUEST_METHOD']) {
// Indicate the URL endpoint, and the JSON-RPC version used:
$server->setTarget('/json-rpc.php')
->setEnvelope(Zend\Json\Server\Smd::ENV_JSONRPC_2);
// Grab the SMD
$smd = $server->getServiceMap();
// Return the SMD to the client
header('Content-Type: application/json');
echo $smd;
return;
}
$server->handle();
```
If utilizing the JSON-RPC server with Dojo toolkit, you will also need to set a special
compatibility flag to ensure that the two interoperate properly:
```php
$server = new Zend\Json\Server\Server();
$server->setClass('Calculator');
if ('GET' == $_SERVER['REQUEST_METHOD']) {
$server->setTarget('/json-rpc.php')
->setEnvelope(Zend\Json\Server\Smd::ENV_JSONRPC_2);
$smd = $server->getServiceMap();
// Set Dojo compatibility:
$smd->setDojoCompatible(true);
header('Content-Type: application/json');
echo $smd;
return;
}
$server->handle();
```
## Advanced Details
While most functionality for `Zend\Json\Server` is spelled out in \[this
section\](zend.json.server.usage), more advanced functionality is available.
### Zend\\Json\\Server\\Server
`Zend\Json\Server\Server` is the core class in the JSON-RPC offering; it handles all requests and
returns the response payload. It has the following methods:
- `addFunction($function)`: Specify a userland function to attach to the server.
- `setClass($class)`: Specify a class or object to attach to the server; all public methods of that
item will be exposed as JSON-RPC methods.
- `fault($fault = null, $code = 404, $data = null)`: Create and return a `Zend\Json\Server\Error`
object.
- `handle($request = false)`: Handle a JSON-RPC request; optionally, pass a
`Zend\Json\Server\Request` object to utilize (creates one by default).
- `getFunctions()`: Return a list of all attached methods.
- `setRequest(Zend\Json\Server\Request $request)`: Specify a request object for the server to
utilize.
- `getRequest()`: Retrieve the request object used by the server.
- `setResponse(Zend\Json\Server\Response $response)`: Set the response object for the server to
utilize.
- `getResponse()`: Retrieve the response object used by the server.
- `setAutoEmitResponse($flag)`: Indicate whether the server should automatically emit the response
and all headers; by default, this is `TRUE`.
- `autoEmitResponse()`: Determine if auto-emission of the response is enabled.
- `getServiceMap()`: Retrieve the service map description in the form of a `Zend\Json\Server\Smd`
object
### Zend\\Json\\Server\\Request
The JSON-RPC request environment is encapsulated in the `Zend\Json\Server\Request` object. This
object allows you to set necessary portions of the JSON-RPC request, including the request ID,
parameters, and JSON-RPC specification version. It has the ability to load itself via *JSON* or a
set of options, and can render itself as *JSON* via the `toJson()` method.
The request object has the following methods available:
- `setOptions(array $options)`: Specify object configuration. `$options` may contain keys matching
any 'set' method: `setParams()`, `setMethod()`, `setId()`, and `setVersion()`.
- `addParam($value, $key = null)`: Add a parameter to use with the method call. Parameters can be
just the values, or can optionally include the parameter name.
- `addParams(array $params)`: Add multiple parameters at once; proxies to `addParam()`
- `setParams(array $params)`: Set all parameters at once; overwrites any existing parameters.
- `getParam($index)`: Retrieve a parameter by position or name.
- `getParams()`: Retrieve all parameters at once.
- `setMethod($name)`: Set the method to call.
- `getMethod()`: Retrieve the method that will be called.
- `isMethodError()`: Determine whether or not the request is malformed and would result in an error.
- `setId($name)`: Set the request identifier (used by the client to match requests to responses).
- `getId()`: Retrieve the request identifier.
- `setVersion($version)`: Set the JSON-RPC specification version the request conforms to. May be
either '1.0' or '2.0'.
- `getVersion()`: Retrieve the JSON-RPC specification version used by the request.
- `loadJson($json)`: Load the request object from a *JSON* string.
- `toJson()`: Render the request as a *JSON* string.
An *HTTP* specific version is available via `Zend\Json\Server\Request\Http`. This class will
retrieve the request via `php://input`, and allows access to the raw *JSON* via the `getRawJson()`
method.
### Zend\\Json\\Server\\Response
The JSON-RPC response payload is encapsulated in the `Zend\Json\Server\Response` object. This object
allows you to set the return value of the request, whether or not the response is an error, the
request identifier, the JSON-RPC specification version the response conforms to, and optionally the
service map.
The response object has the following methods available:
- `setResult($value)`: Set the response result.
- `getResult()`: Retrieve the response result.
- `setError(Zend\Json\Server\Error $error)`: Set an error object. If set, this will be used as the
response when serializing to *JSON*.
- `getError()`: Retrieve the error object, if any.
- `isError()`: Whether or not the response is an error response.
- `setId($name)`: Set the request identifier (so the client may match the response with the original
request).
- `getId()`: Retrieve the request identifier.
- `setVersion($version)`: Set the JSON-RPC version the response conforms to.
- `getVersion()`: Retrieve the JSON-RPC version the response conforms to.
- `toJson()`: Serialize the response to *JSON*. If the response is an error response, serializes the
error object.
- `setServiceMap($serviceMap)`: Set the service map object for the response.
- `getServiceMap()`: Retrieve the service map object, if any.
An *HTTP* specific version is available via `Zend\Json\Server\Response\Http`. This class will send
the appropriate *HTTP* headers as well as serialize the response as *JSON*.
### Zend\\Json\\Server\\Error
JSON-RPC has a special format for reporting error conditions. All errors need to provide, minimally,
an error message and error code; optionally, they can provide additional data, such as a backtrace.
Error codes are derived from those recommended by [the XML-RPC EPI
project](http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php). `Zend\Json\Server`
appropriately assigns the code based on the error condition. For application exceptions, the code
'-32000' is used.
`Zend\Json\Server\Error` exposes the following methods:
- `setCode($code)`: Set the error code; if the code is not in the accepted XML-RPC error code range,
-32000 will be assigned.
- `getCode()`: Retrieve the current error code.
- `setMessage($message)`: Set the error message.
- `getMessage()`: Retrieve the current error message.
- `setData($data)`: Set auxiliary data further qualifying the error, such as a backtrace.
- `getData()`: Retrieve any current auxiliary error data.
- `toArray()`: Cast the error to an array. The array will contain the keys 'code', 'message', and
'data'.
- `toJson()`: Cast the error to a JSON-RPC error representation.
### Zend\\Json\\Server\\Smd
SMD stands for Service Mapping Description, a *JSON* schema that defines how a client can interact
with a particular web service. At the time of this writing, the
[specification](http://www.jsonrpc.org/specification) has not yet been formally ratified, but it is
in use already within Dojo toolkit as well as other JSON-RPC consumer clients.
At its most basic, a Service Mapping Description indicates the method of transport (POST, `GET`,
*TCP*/IP, etc), the request envelope type (usually based on the protocol of the server), the target
*URL* of the service provider, and a map of services available. In the case of JSON-RPC, the service
map is a list of available methods, which each method documenting the available parameters and their
types, as well as the expected return value type.
`Zend\Json\Server\Smd` provides an object-oriented way to build service maps. At its most basic, you
pass it metadata describing the service using mutators, and specify services (methods and
functions).
The service descriptions themselves are typically instances of `Zend\Json\Server\Smd\Service`; you
can also pass all information as an array to the various service mutators in `Zend\Json\Server\Smd`,
and it will instantiate a service for you. The service objects contain information such as the name
of the service (typically the function or method name), the parameters (names, types, and position),
and the return value type. Optionally, each service can have its own target and envelope, though
this functionality is rarely used.
`Zend\Json\Server\Server` actually does all of this behind the scenes for you, by using reflection
on the attached classes and functions; you should create your own service maps only if you need to
provide custom functionality that class and function introspection cannot offer.
Methods available in `Zend\Json\Server\Smd` include:
- `setOptions(array $options)`: Setup an SMD object from an array of options. All mutators (methods
beginning with 'set') can be used as keys.
- `setTransport($transport)`: Set the transport used to access the service; only POST is currently
supported.
- `getTransport()`: Get the current service transport.
- `setEnvelope($envelopeType)`: Set the request envelope that should be used to access the service.
Currently, supports the constants `Zend\Json\Server\Smd::ENV_JSONRPC_1` and
`Zend\Json\Server\Smd::ENV_JSONRPC_2`.
- `getEnvelope()`: Get the current request envelope.
- `setContentType($type)`: Set the content type requests should use (by default, this is
'application/json').
- `getContentType()`: Get the current content type for requests to the service.
- `setTarget($target)`: Set the *URL* endpoint for the service.
- `getTarget()`: Get the *URL* endpoint for the service.
- `setId($id)`: Typically, this is the *URL* endpoint of the service (same as the target).
- `getId()`: Retrieve the service ID (typically the *URL* endpoint of the service).
- `setDescription($description)`: Set a service description (typically narrative information
describing the purpose of the service).
- `getDescription()`: Get the service description.
- `setDojoCompatible($flag)`: Set a flag indicating whether or not the SMD is compatible with Dojo
toolkit. When `TRUE`, the generated *JSON* SMD will be formatted to comply with the format that
Dojo's JSON-RPC client expects.
- `isDojoCompatible()`: Returns the value of the Dojo compatibility flag (`FALSE`, by default).
- `addService($service)`: Add a service to the map. May be an array of information to pass to the
constructor of `Zend\Json\Server\Smd\Service`, or an instance of that class.
- `addServices(array $services)`: Add multiple services at once.
- `setServices(array $services)`: Add multiple services at once, overwriting any previously set
services.
- `getService($name)`: Get a service by its name.
- `getServices()`: Get all attached services.
- `removeService($name)`: Remove a service from the map.
- `toArray()`: Cast the service map to an array.
- `toDojoArray()`: Cast the service map to an array compatible with Dojo Toolkit.
- `toJson()`: Cast the service map to a *JSON* representation.
`Zend\Json\Server\Smd\Service` has the following methods:
- `setOptions(array $options)`: Set object state from an array. Any mutator (methods beginning with
'set') may be used as a key and set via this method.
- `setName($name)`: Set the service name (typically, the function or method name).
- `getName()`: Retrieve the service name.
- `setTransport($transport)`: Set the service transport (currently, only transports supported by
`Zend\Json\Server\Smd` are allowed).
- `getTransport()`: Retrieve the current transport.
- `setTarget($target)`: Set the *URL* endpoint of the service (typically, this will be the same as
the overall SMD to which the service is attached).
- `getTarget()`: Get the *URL* endpoint of the service.
- `setEnvelope($envelopeType)`: Set the service envelope (currently, only envelopes supported by
`Zend\Json\Server\Smd` are allowed).
- `getEnvelope()`: Retrieve the service envelope type.
- `addParam($type, array $options = array(), $order = null)`: Add a parameter to the service. By
default, only the parameter type is necessary. However, you may also specify the order, as well as
options such as:
- **name**: the parameter name
- **optional**: whether or not the parameter is optional
- **default**: a default value for the parameter
- **description**: text describing the parameter
- `addParams(array $params)`: Add several parameters at once; each param should be an assoc array
containing minimally the key 'type' describing the parameter type, and optionally the key 'order';
any other keys will be passed as `$options` to `addOption()`.
- `setParams(array $params)`: Set many parameters at once, overwriting any existing parameters.
- `getParams()`: Retrieve all currently set parameters.
- `setReturn($type)`: Set the return value type of the service.
- `getReturn()`: Get the return value type of the service.
- `toArray()`: Cast the service to an array.
- `toJson()`: Cast the service to a *JSON* representation.

View File

@@ -1,98 +0,0 @@
# XML to JSON conversion
`Zend\Json` provides a convenience method for transforming *XML* formatted data into *JSON* format.
This feature was inspired from an [IBM developerWorks
article](http://www.ibm.com/developerworks/xml/library/x-xml2jsonphp/).
`Zend\Json` includes a static function called `Zend\Json\Json::fromXml()`. This function will
generate *JSON* from a given *XML* input. This function takes any arbitrary *XML* string as an input
parameter. It also takes an optional boolean input parameter to instruct the conversion logic to
ignore or not ignore the *XML* attributes during the conversion process. If this optional input
parameter is not given, then the default behavior is to ignore the *XML* attributes. This function
call is made as shown below:
```php
// fromXml function simply takes a String containing XML contents
// as input.
$jsonContents = Zend\Json\Json::fromXml($xmlStringContents, true);
```
`Zend\Json\Json::fromXml()` function does the conversion of the *XML* formatted string input
parameter and returns the equivalent *JSON* formatted string output. In case of any *XML* input
format error or conversion logic error, this function will throw an exception. The conversion logic
also uses recursive techniques to traverse the *XML* tree. It supports recursion upto 25 levels
deep. Beyond that depth, it will throw a `Zend\Json\Exception`. There are several *XML* files with
varying degree of complexity provided in the tests directory of Zend Framework. They can be used to
test the functionality of the xml2json feature.
## Example
The following is a simple example that shows both the *XML* input string passed to and the *JSON*
output string returned as a result from the `Zend\Json\Json::fromXml()` function. This example used
the optional function parameter as not to ignore the *XML* attributes during the conversion. Hence,
you can notice that the resulting *JSON* string includes a representation of the *XML* attributes
present in the *XML* input string.
*XML* input string passed to `Zend\Json\Json::fromXml()` function:
```php
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1">
<title>Code Generation in Action</title>
<author><first>Jack</first><last>Herrington</last></author>
<publisher>Manning</publisher>
</book>
<book id="2">
<title>PHP Hacks</title>
<author><first>Jack</first><last>Herrington</last></author>
<publisher>O'Reilly</publisher>
</book>
<book id="3">
<title>Podcasting Hacks</title>
<author><first>Jack</first><last>Herrington</last></author>
<publisher>O'Reilly</publisher>
</book>
</books>
```
*JSON* output string returned from `Zend\Json\Json::fromXml()` function:
```php
{
"books" : {
"book" : [ {
"@attributes" : {
"id" : "1"
},
"title" : "Code Generation in Action",
"author" : {
"first" : "Jack", "last" : "Herrington"
},
"publisher" : "Manning"
}, {
"@attributes" : {
"id" : "2"
},
"title" : "PHP Hacks", "author" : {
"first" : "Jack", "last" : "Herrington"
},
"publisher" : "O'Reilly"
}, {
"@attributes" : {
"id" : "3"
},
"title" : "Podcasting Hacks", "author" : {
"first" : "Jack", "last" : "Herrington"
},
"publisher" : "O'Reilly"
}
]}
}
```
More details about this xml2json feature can be found in the original proposal itself. Take a look
at the [Zend\_xml2json
proposal](http://framework.zend.com/wiki/display/ZFPROP/Zend_xml2json+-+Senthil+Nathan).

View File

@@ -1,11 +0,0 @@
{
"title": "Zend\\Json",
"target": "html/",
"content": [
"book/zend.json.introduction.md",
"book/zend.json.basics.md",
"book/zend.json.objects.md",
"book/zend.json.xml2json.md",
"book/zend.json.server.md"
]
}

View File

@@ -1,10 +1,8 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json;
@@ -70,7 +68,7 @@ class Decoder
protected $decodeType;
/**
* @var $_tokenValue
* @var mixed
*/
protected $tokenValue;
@@ -99,7 +97,7 @@ class Decoder
// single, escaped unicode character
$utf16 = chr(hexdec(substr($chrs, ($i + 2), 2)))
. chr(hexdec(substr($chrs, ($i + 4), 2)));
$utf8char = self::_utf162utf8($utf16);
$utf8char = self::utf162utf8($utf16);
$search = ['\\', "\n", "\t", "\r", chr(0x08), chr(0x0C), '"', '\'', '/'];
if (in_array($utf8char, $search)) {
$replace = ['\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\\"', '\\\'', '\\/'];
@@ -109,7 +107,7 @@ class Decoder
$i += 5;
break;
case ($ordChrsC >= 0x20) && ($ordChrsC <= 0x7F):
$utf8 .= $chrs{$i};
$utf8 .= $chrs[$i];
break;
case ($ordChrsC & 0xE0) == 0xC0:
// characters U-00000080 - U-000007FF, mask 110XXXXX
@@ -152,8 +150,8 @@ class Decoder
*
* @param string $source String source to decode
* @param int $decodeType How objects should be decoded -- see
* {@link Zend\Json\Json::TYPE_ARRAY} and {@link Zend\Json\Json::TYPE_OBJECT} for
* valid values
* {@link Json::TYPE_ARRAY} and {@link Json::TYPE_OBJECT} for * valid
* values
* @throws InvalidArgumentException
*/
protected function __construct($source, $decodeType)
@@ -170,72 +168,73 @@ class Decoder
$this->decodeType = $decodeType;
break;
default:
throw new InvalidArgumentException("Unknown decode type '{$decodeType}', please use one of the constants Json::TYPE_*");
throw new InvalidArgumentException(sprintf(
'Unknown decode type "%s", please use one of the Json::TYPE_* constants',
$decodeType
));
}
// Set pointer at first token
$this->_getNextToken();
$this->getNextToken();
}
/**
* Decode a JSON source string
* Decode a JSON source string.
*
* Decodes a JSON encoded string. The value returned will be one of the
* Decodes a JSON encoded string; the value returned will be one of the
* following:
* - integer
* - float
* - boolean
* - null
* - stdClass
* - array
* - array of one or more of the above types
*
* By default, decoded objects will be returned as associative arrays; to
* return a stdClass object instead, pass {@link Zend\Json\Json::TYPE_OBJECT} to
* the $objectDecodeType parameter.
* - integer
* - float
* - boolean
* - null
* - stdClass
* - array
* - array of one or more of the above types
*
* @static
* @access public
* @param string $source String to be decoded
* By default, decoded objects will be returned as a stdClass object;
* to return associative arrays instead, pass {@link Json::TYPE_ARRAY}
* to the $objectDecodeType parameter.
*
* @param string $source String to be decoded.
* @param int $objectDecodeType How objects should be decoded; should be
* either or {@link Zend\Json\Json::TYPE_ARRAY} or
* {@link Zend\Json\Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
* either or {@link Json::TYPE_ARRAY} or {@link Json::TYPE_OBJECT};
* defaults to Json::TYPE_OBJECT.
* @return mixed
*/
public static function decode($source, $objectDecodeType = Json::TYPE_OBJECT)
{
$decoder = new static($source, $objectDecodeType);
return $decoder->_decodeValue();
return $decoder->decodeValue();
}
/**
* Recursive driving routine for supported toplevel tops
* Recursive routine for supported toplevel types.
*
* @return mixed
*/
protected function _decodeValue()
protected function decodeValue()
{
switch ($this->token) {
case self::DATUM:
$result = $this->tokenValue;
$this->_getNextToken();
$this->getNextToken();
return($result);
case self::LBRACE:
return($this->_decodeObject());
return($this->decodeObject());
case self::LBRACKET:
return($this->_decodeArray());
return($this->decodeArray());
default:
return;
}
}
/**
* Decodes an object of the form:
* { "attribute: value, "attribute2" : value,...}
* Decodes an object of the form { "attribute: value, "attribute2" : value, ... }
*
* If Zend\Json\Encoder was used to encode the original object then
* a special attribute called __className which specifies a class
* name that should wrap the data contained within the encoded source.
* If Zend\Json\Encoder was used to encode the original object, then
* a special attribute called __className will specify a class
* name with which to wrap the data contained within the encoded source.
*
* Decodes to either an array or stdClass object, based on the value of
* {@link $decodeType}. If invalid $decodeType present, returns as an
@@ -244,36 +243,36 @@ class Decoder
* @return array|stdClass
* @throws RuntimeException
*/
protected function _decodeObject()
protected function decodeObject()
{
$members = [];
$tok = $this->_getNextToken();
$tok = $this->getNextToken();
while ($tok && $tok != self::RBRACE) {
if ($tok != self::DATUM || ! is_string($this->tokenValue)) {
throw new RuntimeException('Missing key in object encoding: ' . $this->source);
while ($tok && $tok !== self::RBRACE) {
if ($tok !== self::DATUM || ! is_string($this->tokenValue)) {
throw new RuntimeException(sprintf('Missing key in object encoding: %s', $this->source));
}
$key = $this->tokenValue;
$tok = $this->_getNextToken();
$tok = $this->getNextToken();
if ($tok != self::COLON) {
throw new RuntimeException('Missing ":" in object encoding: ' . $this->source);
if ($tok !== self::COLON) {
throw new RuntimeException(sprintf('Missing ":" in object encoding: %s', $this->source));
}
$this->_getNextToken();
$members[$key] = $this->_decodeValue();
$this->getNextToken();
$members[$key] = $this->decodeValue();
$tok = $this->token;
if ($tok == self::RBRACE) {
if ($tok === self::RBRACE) {
break;
}
if ($tok != self::COMMA) {
throw new RuntimeException('Missing "," in object encoding: ' . $this->source);
if ($tok !== self::COMMA) {
throw new RuntimeException(sprintf('Missing "," in object encoding: %s', $this->source));
}
$tok = $this->_getNextToken();
$tok = $this->getNextToken();
}
switch ($this->decodeType) {
@@ -288,70 +287,71 @@ class Decoder
}
break;
case Json::TYPE_ARRAY:
// intentionally fall-through
default:
$result = $members;
break;
}
$this->_getNextToken();
$this->getNextToken();
return $result;
}
/**
* Decodes a JSON array format:
* [element, element2,...,elementN]
* Decodes the JSON array format [element, element2, ..., elementN]
*
* @return array
* @throws RuntimeException
*/
protected function _decodeArray()
protected function decodeArray()
{
$result = [];
$tok = $this->_getNextToken(); // Move past the '['
$tok = $this->getNextToken(); // Move past the '['
$index = 0;
while ($tok && $tok != self::RBRACKET) {
$result[$index++] = $this->_decodeValue();
while ($tok && $tok !== self::RBRACKET) {
$result[$index++] = $this->decodeValue();
$tok = $this->token;
if ($tok == self::RBRACKET || !$tok) {
if ($tok == self::RBRACKET || ! $tok) {
break;
}
if ($tok != self::COMMA) {
throw new RuntimeException('Missing "," in array encoding: ' . $this->source);
if ($tok !== self::COMMA) {
throw new RuntimeException(sprintf('Missing "," in array encoding: %s', $this->source));
}
$tok = $this->_getNextToken();
$tok = $this->getNextToken();
}
$this->_getNextToken();
$this->getNextToken();
return $result;
}
/**
* Removes whitespace characters from the source input
* Removes whitespace characters from the source input.
*/
protected function _eatWhitespace()
protected function eatWhitespace()
{
if (preg_match('/([\t\b\f\n\r ])*/s', $this->source, $matches, PREG_OFFSET_CAPTURE, $this->offset)
&& $matches[0][1] == $this->offset) {
&& $matches[0][1] == $this->offset
) {
$this->offset += strlen($matches[0][0]);
}
}
/**
* Retrieves the next token from the source stream
* Retrieves the next token from the source stream.
*
* @return int Token constant value specified in class definition
* @return int Token constant value specified in class definition.
* @throws RuntimeException
*/
protected function _getNextToken()
protected function getNextToken()
{
$this->token = self::EOF;
$this->tokenValue = null;
$this->_eatWhitespace();
$this->eatWhitespace();
if ($this->offset >= $this->sourceLength) {
return(self::EOF);
@@ -362,7 +362,7 @@ class Decoder
$i = $this->offset;
$start = $i;
switch ($str{$i}) {
switch ($str[$i]) {
case '{':
$this->token = self::LBRACE;
break;
@@ -389,72 +389,76 @@ class Decoder
break;
}
$chr = $str{$i};
$chr = $str[$i];
if ($chr == '\\') {
$i++;
if ($i >= $strLength) {
break;
}
$chr = $str{$i};
switch ($chr) {
case '"':
$result .= '"';
break;
case '\\':
$result .= '\\';
break;
case '/':
$result .= '/';
break;
case 'b':
$result .= "\x08";
break;
case 'f':
$result .= "\x0c";
break;
case 'n':
$result .= "\x0a";
break;
case 'r':
$result .= "\x0d";
break;
case 't':
$result .= "\x09";
break;
case '\'':
$result .= '\'';
break;
default:
throw new RuntimeException("Illegal escape sequence '{$chr}'");
}
} elseif ($chr == '"') {
if ($chr === '"') {
break;
} else {
}
if ($chr !== '\\') {
$result .= $chr;
continue;
}
$i++;
if ($i >= $strLength) {
break;
}
$chr = $str[$i];
switch ($chr) {
case '"':
$result .= '"';
break;
case '\\':
$result .= '\\';
break;
case '/':
$result .= '/';
break;
case 'b':
$result .= "\x08";
break;
case 'f':
$result .= "\x0c";
break;
case 'n':
$result .= "\x0a";
break;
case 'r':
$result .= "\x0d";
break;
case 't':
$result .= "\x09";
break;
case '\'':
$result .= '\'';
break;
default:
throw new RuntimeException(sprintf('Illegal escape sequence "%s"', $chr));
}
} while ($i < $strLength);
$this->token = self::DATUM;
//$this->tokenValue = substr($str, $start + 1, $i - $start - 1);
$this->tokenValue = $result;
break;
case 't':
if (($i+ 3) < $strLength && substr($str, $start, 4) == "true") {
if (($i + 3) < $strLength && $start === strpos($str, "true", $start)) {
$this->token = self::DATUM;
}
$this->tokenValue = true;
$i += 3;
break;
case 'f':
if (($i+ 4) < $strLength && substr($str, $start, 5) == "false") {
if (($i + 4) < $strLength && $start === strpos($str, "false", $start)) {
$this->token = self::DATUM;
}
$this->tokenValue = false;
$i += 4;
break;
case 'n':
if (($i+ 3) < $strLength && substr($str, $start, 4) == "null") {
if (($i + 3) < $strLength && $start === strpos($str, "null", $start)) {
$this->token = self::DATUM;
}
$this->tokenValue = null;
@@ -462,78 +466,81 @@ class Decoder
break;
}
if ($this->token != self::EOF) {
if ($this->token !== self::EOF) {
$this->offset = $i + 1; // Consume the last token character
return($this->token);
return ($this->token);
}
$chr = $str{$i};
if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s', $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
$datum = $matches[0][0];
$chr = $str[$i];
if (is_numeric($datum)) {
if (preg_match('/^0\d+$/', $datum)) {
throw new RuntimeException("Octal notation not supported by JSON (value: {$datum})");
} else {
$val = intval($datum);
$fVal = floatval($datum);
$this->tokenValue = ($val == $fVal ? $val : $fVal);
}
} else {
throw new RuntimeException("Illegal number format: {$datum}");
}
$this->token = self::DATUM;
$this->offset = $start + strlen($datum);
}
} else {
if ($chr !== '-' && $chr !== '.' && ($chr < '0' || $chr > '9')) {
throw new RuntimeException('Illegal Token');
}
if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s', $str, $matches, PREG_OFFSET_CAPTURE, $start)
&& $matches[0][1] == $start
) {
$datum = $matches[0][0];
if (! is_numeric($datum)) {
throw new RuntimeException(sprintf('Illegal number format: %s', $datum));
}
if (preg_match('/^0\d+$/', $datum)) {
throw new RuntimeException(sprintf('Octal notation not supported by JSON (value: %o)', $datum));
}
$val = intval($datum);
$fVal = floatval($datum);
$this->tokenValue = ($val == $fVal ? $val : $fVal);
$this->token = self::DATUM;
$this->offset = $start + strlen($datum);
}
return $this->token;
}
/**
* Convert a string from one UTF-16 char to one UTF-8 char.
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibyte string extension.
* Normally should be handled by mb_convert_encoding, but provides a slower
* PHP-only method for installations that lack the multibyte string
* extension.
*
* This method is from the Solar Framework by Paul M. Jones
* This method is from the Solar Framework by Paul M. Jones.
*
* @link http://solarphp.com
* @param string $utf16 UTF-16 character
* @return string UTF-8 character
*/
protected static function _utf162utf8($utf16)
protected static function utf162utf8($utf16)
{
// Check for mb extension otherwise do by hand.
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
}
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
$bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
switch (true) {
case ((0x7F & $bytes) == $bytes):
// this case should never be reached, because we are in ASCII range
// This case should never be reached, because we are in ASCII range;
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x7F & $bytes);
case (0x07FF & $bytes) == $bytes:
// return a 2-byte UTF-8 character
// Return a 2-byte UTF-8 character;
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xC0 | (($bytes >> 6) & 0x1F))
. chr(0x80 | ($bytes & 0x3F));
. chr(0x80 | ($bytes & 0x3F));
case (0xFFFF & $bytes) == $bytes:
// return a 3-byte UTF-8 character
// Return a 3-byte UTF-8 character;
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xE0 | (($bytes >> 12) & 0x0F))
. chr(0x80 | (($bytes >> 6) & 0x3F))
. chr(0x80 | ($bytes & 0x3F));
. chr(0x80 | (($bytes >> 6) & 0x3F))
. chr(0x80 | ($bytes & 0x3F));
}
// ignoring UTF-32 for now, sorry

View File

@@ -1,10 +1,8 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json;
@@ -17,19 +15,19 @@ use Zend\Json\Exception\InvalidArgumentException;
use Zend\Json\Exception\RecursionException;
/**
* Encode PHP constructs to JSON
* Encode PHP constructs to JSON.
*/
class Encoder
{
/**
* Whether or not to check for possible cycling
* Whether or not to check for possible cycling.
*
* @var bool
*/
protected $cycleCheck;
/**
* Additional options used during encoding
* Additional options used during encoding.
*
* @var array
*/
@@ -43,27 +41,24 @@ class Encoder
protected $visited = [];
/**
* Constructor
*
* @param bool $cycleCheck Whether or not to check for recursion when encoding
* @param array $options Additional options used during encoding
* @return Encoder
* @param bool $cycleCheck Whether or not to check for recursion when encoding.
* @param array $options Additional options used during encoding.
*/
protected function __construct($cycleCheck = false, $options = [])
protected function __construct($cycleCheck = false, array $options = [])
{
$this->cycleCheck = $cycleCheck;
$this->options = $options;
}
/**
* Use the JSON encoding scheme for the value specified
* Use the JSON encoding scheme for the value specified.
*
* @param mixed $value The value to be encoded
* @param bool $cycleCheck Whether or not to check for possible object recursion when encoding
* @param array $options Additional options used during encoding
* @return string The encoded value
* @param mixed $value The value to be encoded.
* @param bool $cycleCheck Whether or not to check for possible object recursion when encoding.
* @param array $options Additional options used during encoding.
* @return string The encoded value.
*/
public static function encode($value, $cycleCheck = false, $options = [])
public static function encode($value, $cycleCheck = false, array $options = [])
{
$encoder = new static($cycleCheck, $options);
@@ -71,55 +66,62 @@ class Encoder
$value = $value->jsonSerialize();
}
return $encoder->_encodeValue($value);
return $encoder->encodeValue($value);
}
/**
* Recursive driver which determines the type of value to be encoded
* and then dispatches to the appropriate method. $values are either
* - objects (returns from {@link _encodeObject()})
* - arrays (returns from {@link _encodeArray()})
* - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
* Encode a value to JSON.
*
* @param $value mixed The value to be encoded
* @return string Encoded value
* Recursive method which determines the type of value to be encoded
* and then dispatches to the appropriate method.
*
* $values are either
* - objects (returns from {@link encodeObject()})
* - arrays (returns from {@link encodeArray()})
* - scalars (returns from {@link encodeDatum()})
*
* @param $value mixed The value to be encoded.
* @return string Encoded value.
*/
protected function _encodeValue(&$value)
protected function encodeValue(&$value)
{
if (is_object($value)) {
return $this->_encodeObject($value);
} elseif (is_array($value)) {
return $this->_encodeArray($value);
return $this->encodeObject($value);
}
return $this->_encodeDatum($value);
if (is_array($value)) {
return $this->encodeArray($value);
}
return $this->encodeDatum($value);
}
/**
* Encode an object to JSON by encoding each of the public properties
* Encode an object to JSON by encoding each of the public properties.
*
* A special property is added to the JSON object called '__className'
* that contains the name of the class of $value. This is used to decode
* the object on the client into a specific class.
* A special property is added to the JSON object called '__className' that
* contains the classname of $value; this can be used by consumers of the
* resulting JSON to cast to the specific class.
*
* @param $value object
* @return string
* @throws RecursionException If recursive checks are enabled and the
* object has been serialized previously
* object has been serialized previously.
*/
protected function _encodeObject(&$value)
protected function encodeObject(&$value)
{
if ($this->cycleCheck) {
if ($this->_wasVisited($value)) {
if (isset($this->options['silenceCyclicalExceptions'])
&& $this->options['silenceCyclicalExceptions']===true) {
return '"* RECURSION (' . str_replace('\\', '\\\\', get_class($value)) . ') *"';
} else {
throw new RecursionException(
'Cycles not supported in JSON encoding, cycle introduced by '
. 'class "' . get_class($value) . '"'
);
if ($this->wasVisited($value)) {
if (! isset($this->options['silenceCyclicalExceptions'])
|| $this->options['silenceCyclicalExceptions'] !== true
) {
throw new RecursionException(sprintf(
'Cycles not supported in JSON encoding; cycle introduced by class "%s"',
get_class($value)
));
}
return '"* RECURSION (' . str_replace('\\', '\\\\', get_class($value)) . ') *"';
}
$this->visited[] = $value;
@@ -139,28 +141,30 @@ class Encoder
}
foreach ($propCollection as $name => $propValue) {
if (isset($propValue)) {
$props .= ','
. $this->_encodeValue($name)
. ':'
. $this->_encodeValue($propValue);
if (! isset($propValue)) {
continue;
}
$props .= ','
. $this->encodeValue($name)
. ':'
. $this->encodeValue($propValue);
}
}
$className = get_class($value);
return '{"__className":'
. $this->_encodeString($className)
. $this->encodeString($className)
. $props . '}';
}
/**
* Determine if an object has been serialized already
* Determine if an object has been serialized already.
*
* @param mixed $value
* @return bool
*/
protected function _wasVisited(&$value)
protected function wasVisited(&$value)
{
if (in_array($value, $this->visited, true)) {
return true;
@@ -170,86 +174,110 @@ class Encoder
}
/**
* JSON encode an array value
* JSON encode an array value.
*
* Recursively encodes each value of an array and returns a JSON encoded
* array string.
*
* Arrays are defined as integer-indexed arrays starting at index 0, where
* the last index is (count($array) -1); any deviation from that is
* considered an associative array, and will be encoded as such.
* considered an associative array, and will be passed to
* {@link encodeAssociativeArray()}.
*
* @param $array array
* @return string
*/
protected function _encodeArray(&$array)
protected function encodeArray($array)
{
$tmpArray = [];
// Check for associative array
if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
if (! empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
// Associative array
$result = '{';
foreach ($array as $key => $value) {
$key = (string) $key;
$tmpArray[] = $this->_encodeString($key)
. ':'
. $this->_encodeValue($value);
}
$result .= implode(',', $tmpArray);
$result .= '}';
} else {
// Indexed array
$result = '[';
$length = count($array);
for ($i = 0; $i < $length; $i++) {
$tmpArray[] = $this->_encodeValue($array[$i]);
}
$result .= implode(',', $tmpArray);
$result .= ']';
return $this->encodeAssociativeArray($array);
}
// Indexed array
$tmpArray = [];
$result = '[';
$length = count($array);
for ($i = 0; $i < $length; $i++) {
$tmpArray[] = $this->encodeValue($array[$i]);
}
$result .= implode(',', $tmpArray);
$result .= ']';
return $result;
}
/**
* JSON encode a basic data type (string, number, boolean, null)
* Encode an associative array to JSON.
*
* JSON does not have a concept of associative arrays; as such, we encode
* them to objects.
*
* @param array $array Array to encode.
* @return string
*/
protected function encodeAssociativeArray($array)
{
$tmpArray = [];
$result = '{';
foreach ($array as $key => $value) {
$tmpArray[] = sprintf(
'%s:%s',
$this->encodeString((string) $key),
$this->encodeValue($value)
);
}
$result .= implode(',', $tmpArray);
$result .= '}';
return $result;
}
/**
* JSON encode a scalar data type (string, number, boolean, null).
*
* If value type is not a string, number, boolean, or null, the string
* 'null' is returned.
*
* @param mixed $value
* @param mixed $value
* @return string
*/
protected function _encodeDatum(&$value)
protected function encodeDatum($value)
{
$result = 'null';
if (is_int($value) || is_float($value)) {
$result = (string) $value;
$result = str_replace(',', '.', $result);
} elseif (is_string($value)) {
$result = $this->_encodeString($value);
} elseif (is_bool($value)) {
$result = $value ? 'true' : 'false';
return str_replace(',', '.', (string) $value);
}
return $result;
if (is_string($value)) {
return $this->encodeString($value);
}
if (is_bool($value)) {
return $value ? 'true' : 'false';
}
return 'null';
}
/**
* JSON encode a string value by escaping characters as necessary
* JSON encode a string value by escaping characters as necessary.
*
* @param string $string
* @return string
*/
protected function _encodeString(&$string)
protected function encodeString($string)
{
// @codingStandardsIgnoreStart
// Escape these characters with a backslash or unicode escape:
// " \ / \n \r \t \b \f
$search = ['\\', "\n", "\t", "\r", "\b", "\f", '"', '\'', '&', '<', '>', '/'];
$replace = ['\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\\u0022', '\\u0027', '\\u0026', '\\u003C', '\\u003E', '\\/'];
$replace = ['\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\\u0022', '\\u0027', '\\u0026', '\\u003C', '\\u003E', '\\/'];
$string = str_replace($search, $replace, $string);
// @codingStandardsIgnoreEnd
// Escape certain ASCII characters:
// 0x08 => \b
@@ -261,45 +289,45 @@ class Encoder
}
/**
* Encode the constants associated with the ReflectionClass
* parameter. The encoding format is based on the class2 format
* Encode the constants associated with the ReflectionClass parameter.
*
* @param ReflectionClass $cls
* The encoding format is based on the class2 format.
*
* @param ReflectionClass $class
* @return string Encoded constant block in class2 format
*/
private static function _encodeConstants(ReflectionClass $cls)
private static function encodeConstants(ReflectionClass $class)
{
$result = "constants : {";
$constants = $cls->getConstants();
$result = "constants:{";
$constants = $class->getConstants();
if (empty($constants)) {
return $result . '}';
}
$tmpArray = [];
if (!empty($constants)) {
foreach ($constants as $key => $value) {
$tmpArray[] = "$key: " . self::encode($value);
}
$result .= implode(', ', $tmpArray);
foreach ($constants as $key => $value) {
$tmpArray[] = sprintf('%s: %s', $key, self::encode($value));
}
$result .= implode(', ', $tmpArray);
return $result . "}";
}
/**
* Encode the public methods of the ReflectionClass in the
* class2 format
*
* @param ReflectionClass $cls
* @return string Encoded method fragment
* Encode the public methods of the ReflectionClass in the class2 format
*
* @param ReflectionClass $class
* @return string Encoded method fragment.
*/
private static function _encodeMethods(ReflectionClass $cls)
private static function encodeMethods(ReflectionClass $class)
{
$methods = $cls->getMethods();
$result = 'methods:{';
$result = 'methods:{';
$started = false;
foreach ($methods as $method) {
if (! $method->isPublic() || !$method->isUserDefined()) {
foreach ($class->getMethods() as $method) {
if (! $method->isPublic() || ! $method->isUserDefined()) {
continue;
}
@@ -308,105 +336,110 @@ class Encoder
}
$started = true;
$result .= '' . $method->getName(). ':function(';
$result .= sprintf('%s:function(', $method->getName());
if ('__construct' != $method->getName()) {
$parameters = $method->getParameters();
$argsStarted = false;
$argNames = "var argNames=[";
foreach ($parameters as $param) {
if ($argsStarted) {
$result .= ',';
}
$result .= $param->getName();
if ($argsStarted) {
$argNames .= ',';
}
$argNames .= '"' . $param->getName() . '"';
$argsStarted = true;
}
$argNames .= "];";
$result .= "){"
. $argNames
. 'var result = ZAjaxEngine.invokeRemoteMethod('
. "this, '" . $method->getName()
. "',argNames,arguments);"
. 'return(result);}';
} else {
$result .= "){}";
if ('__construct' === $method->getName()) {
$result .= '){}';
continue;
}
$argsStarted = false;
$argNames = "var argNames=[";
foreach ($method->getParameters() as $param) {
if ($argsStarted) {
$result .= ',';
}
$result .= $param->getName();
if ($argsStarted) {
$argNames .= ',';
}
$argNames .= sprintf('"%s"', $param->getName());
$argsStarted = true;
}
$argNames .= "];";
$result .= "){"
. $argNames
. 'var result = ZAjaxEngine.invokeRemoteMethod('
. "this, '"
. $method->getName()
. "',argNames,arguments);"
. 'return(result);}';
}
return $result . "}";
}
/**
* Encode the public properties of the ReflectionClass in the class2
* format.
* Encode the public properties of the ReflectionClass in the class2 format.
*
* @param ReflectionClass $cls
* @param ReflectionClass $class
* @return string Encode properties list
*
*/
private static function _encodeVariables(ReflectionClass $cls)
private static function encodeVariables(ReflectionClass $class)
{
$properties = $cls->getProperties();
$propValues = get_class_vars($cls->getName());
$result = "variables:{";
$propValues = get_class_vars($class->getName());
$result = "variables:{";
$tmpArray = [];
$tmpArray = [];
foreach ($properties as $prop) {
foreach ($class->getProperties() as $prop) {
if (! $prop->isPublic()) {
continue;
}
$tmpArray[] = $prop->getName()
. ':'
. self::encode($propValues[$prop->getName()]);
$name = $prop->getName();
$tmpArray[] = sprintf('%s:%s', $name, self::encode($propValues[$name]));
}
$result .= implode(',', $tmpArray);
return $result . "}";
}
/**
* Encodes the given $className into the class2 model of encoding PHP
* classes into JavaScript class2 classes.
* NOTE: Currently only public methods and variables are proxied onto
* the client machine
* Encodes the given $className into the class2 model of encoding PHP classes into JavaScript class2 classes.
*
* NOTE: Currently only public methods and variables are proxied onto the
* client machine
*
* @param $className string The name of the class, the class must be
* instantiable using a null constructor
* instantiable using a null constructor.
* @param $package string Optional package name appended to JavaScript
* proxy class name
* @return string The class2 (JavaScript) encoding of the class
* proxy class name.
* @return string The class2 (JavaScript) encoding of the class.
* @throws InvalidArgumentException
*/
public static function encodeClass($className, $package = '')
{
$cls = new \ReflectionClass($className);
if (! $cls->isInstantiable()) {
throw new InvalidArgumentException("'{$className}' must be instantiable");
$class = new ReflectionClass($className);
if (! $class->isInstantiable()) {
throw new InvalidArgumentException(sprintf(
'"%s" must be instantiable',
$className
));
}
return "Class.create('$package$className',{"
. self::_encodeConstants($cls) .","
. self::_encodeMethods($cls) .","
. self::_encodeVariables($cls) .'});';
return sprintf(
'Class.create(\'%s%s\',{%s,%s,%s});',
$package,
$className,
self::encodeConstants($class),
self::encodeMethods($class),
self::encodeVariables($class)
);
}
/**
* Encode several classes at once
* Encode several classes at once.
*
* Returns JSON encoded classes, using {@link encodeClass()}.
*
* @param array $classNames
* @param string[] $classNames
* @param string $package
* @return string
*/
@@ -423,8 +456,8 @@ class Encoder
/**
* Encode Unicode Characters to \u0000 ASCII syntax.
*
* This algorithm was originally developed for the
* Solar Framework by Paul M. Jones
* This algorithm was originally developed for the Solar Framework by Paul
* M. Jones.
*
* @link http://solarphp.com/
* @link https://github.com/solarphp/core/blob/master/Solar/Json.php
@@ -434,12 +467,10 @@ class Encoder
public static function encodeUnicodeString($value)
{
$strlenVar = strlen($value);
$ascii = "";
$ascii = "";
/**
* Iterate over every character in the string,
* escaping with a slash or encoding to UTF-8 where necessary
*/
// Iterate over every character in the string, escaping with a slash or
// encoding to UTF-8 where necessary.
for ($i = 0; $i < $strlenVar; $i++) {
$ordVarC = ord($value[$i]);
@@ -454,7 +485,7 @@ class Encoder
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ordVarC, ord($value[$i + 1]));
$i += 1;
$utf16 = self::_utf82utf16($char);
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
@@ -468,7 +499,7 @@ class Encoder
ord($value[$i + 2])
);
$i += 2;
$utf16 = self::_utf82utf16($char);
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
@@ -483,7 +514,7 @@ class Encoder
ord($value[$i + 3])
);
$i += 3;
$utf16 = self::_utf82utf16($char);
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
@@ -499,7 +530,7 @@ class Encoder
ord($value[$i + 4])
);
$i += 4;
$utf16 = self::_utf82utf16($char);
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
@@ -516,7 +547,7 @@ class Encoder
ord($value[$i + 5])
);
$i += 5;
$utf16 = self::_utf82utf16($char);
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
}
@@ -528,17 +559,17 @@ class Encoder
/**
* Convert a string from one UTF-8 char to one UTF-16 char.
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibyte string extension.
* Normally should be handled by mb_convert_encoding, but provides a slower
* PHP-only method for installations that lack the multibyte string
* extension.
*
* This method is from the Solar Framework by Paul M. Jones
* This method is from the Solar Framework by Paul M. Jones.
*
* @link http://solarphp.com
* @link http://solarphp.com
* @param string $utf8 UTF-8 character
* @return string UTF-16 character
*/
protected static function _utf82utf16($utf8)
protected static function utf82utf16($utf8)
{
// Check for mb extension otherwise do by hand.
if (function_exists('mb_convert_encoding')) {
@@ -547,19 +578,21 @@ class Encoder
switch (strlen($utf8)) {
case 1:
// this case should never be reached, because we are in ASCII range
// This case should never be reached, because we are in ASCII range;
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return $utf8;
case 2:
// return a UTF-16 character from a 2-byte UTF-8 char
// Return a UTF-16 character from a 2-byte UTF-8 char;
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x07 & (ord($utf8{0}) >> 2)) . chr((0xC0 & (ord($utf8{0}) << 6)) | (0x3F & ord($utf8{1})));
return chr(0x07 & (ord($utf8[0]) >> 2)) . chr((0xC0 & (ord($utf8[0]) << 6)) | (0x3F & ord($utf8[1])));
case 3:
// return a UTF-16 character from a 3-byte UTF-8 char
// Return a UTF-16 character from a 3-byte UTF-8 char;
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr((0xF0 & (ord($utf8{0}) << 4)) | (0x0F & (ord($utf8{1}) >> 2))) . chr((0xC0 & (ord($utf8{1}) << 6)) | (0x7F & ord($utf8{2})));
return chr((0xF0 & (ord($utf8[0]) << 4))
| (0x0F & (ord($utf8[1]) >> 2))) . chr((0xC0 & (ord($utf8[1]) << 6))
| (0x7F & ord($utf8[2])));
}
// ignoring UTF-32 for now, sorry

View File

@@ -1,15 +1,12 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json\Exception;
class BadMethodCallException extends \BadMethodCallException implements
ExceptionInterface
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}

View File

@@ -1,10 +1,8 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json\Exception;

View File

@@ -1,15 +1,12 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements
ExceptionInterface
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -1,10 +1,8 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json\Exception;

View File

@@ -1,10 +1,8 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json\Exception;

View File

@@ -1,22 +1,21 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-json for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-json/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Json;
/**
* Class for Zend\Json\Json encode method.
* Encode a string to a native JavaScript expression.
*
* This class simply holds a string with a native Javascript Expression,
* so objects | arrays to be encoded with Zend\Json\Json can contain native
* Javascript Expressions.
* This class simply holds a string with a native JavaScript expression,
* so objects or arrays to be encoded with Zend\Json\Json can contain native
* JavaScript expressions.
*
* Example:
*
* <code>
* $foo = array(
* 'integer' => 9,
@@ -26,9 +25,17 @@ namespace Zend\Json;
* ),
* );
*
* Zend\Json\Json::encode($foo, false, array('enableJsonExprFinder' => true));
* // it will returns json encoded string:
* // {"integer":9,"string":"test string","function":function () {window.alert("javascript function encoded by Zend\Json\Json")}}
* echo Zend\Json\Json::encode($foo, false, ['enableJsonExprFinder' => true]);
* </code>
*
* The above returns the following JSON (formatted for readability):
*
* <code>
* {
* "integer": 9,
* "string": "test string",
* "function": function () {window.alert("javascript function encoded by Zend\Json\Json")}
* }
* </code>
*/
class Expr
@@ -41,9 +48,7 @@ class Expr
protected $expression;
/**
* Constructor
*
* @param string $expression the expression to hold.
* @param string $expression The expression to represent.
*/
public function __construct($expression)
{

Some files were not shown because too many files have changed in this diff Show More