Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/3rdparty.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoeland Jago Douma <roeland@famdouma.nl>2019-05-15 16:20:16 +0300
committerRoeland Jago Douma <roeland@famdouma.nl>2019-05-15 16:20:16 +0300
commit793150ff5c84584b3d2fba9ddbdf9069d65d0d19 (patch)
tree4f746e05d0102e5d81790ab1a0bfd96c259c8c62 /guzzlehttp
parent35087f0ce01cfb32ad75f9db53196e5818d449f6 (diff)
Vendor in aws-sdk-php
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'guzzlehttp')
-rw-r--r--guzzlehttp/psr7/CHANGELOG.md231
-rw-r--r--guzzlehttp/psr7/README.md8
-rw-r--r--guzzlehttp/psr7/composer.json14
-rw-r--r--guzzlehttp/psr7/src/AppendStream.php16
-rw-r--r--guzzlehttp/psr7/src/FnStream.php9
-rw-r--r--guzzlehttp/psr7/src/InflateStream.php2
-rw-r--r--guzzlehttp/psr7/src/Request.php4
-rw-r--r--guzzlehttp/psr7/src/Response.php4
-rw-r--r--guzzlehttp/psr7/src/Rfc7230.php18
-rw-r--r--guzzlehttp/psr7/src/ServerRequest.php32
-rw-r--r--guzzlehttp/psr7/src/Stream.php39
-rw-r--r--guzzlehttp/psr7/src/StreamWrapper.php46
-rw-r--r--guzzlehttp/psr7/src/Uri.php88
-rw-r--r--guzzlehttp/psr7/src/functions.php130
14 files changed, 492 insertions, 149 deletions
diff --git a/guzzlehttp/psr7/CHANGELOG.md b/guzzlehttp/psr7/CHANGELOG.md
index 5c252b3a..27b65f09 100644
--- a/guzzlehttp/psr7/CHANGELOG.md
+++ b/guzzlehttp/psr7/CHANGELOG.md
@@ -1,32 +1,82 @@
-# CHANGELOG
+# Change Log
-## 1.4.2 - 2017-03-20
-* Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+
+## [Unreleased]
+
+
+## [1.5.2] - 2018-12-04
+
+### Fixed
+
+- Check body size when getting the message summary
+
+
+## [1.5.1] - 2018-12-04
+
+### Fixed
+
+- Get the summary of a body only if it is readable
+
+
+## [1.5.0] - 2018-12-03
+
+### Added
+
+- Response first-line to response string exception (fixes #145)
+- A test for #129 behavior
+- `get_message_body_summary` function in order to get the message summary
+- `3gp` and `mkv` mime types
+
+### Changed
+
+- Clarify exception message when stream is detached
+
+### Deprecated
+
+- Deprecated parsing folded header lines as per RFC 7230
+
+### Fixed
+
+- Fix `AppendStream::detach` to not close streams
+- `InflateStream` preserves `isSeekable` attribute of the underlying stream
+- `ServerRequest::getUriFromGlobals` to support URLs in query parameters
+
+
+Several other fixes and improvements.
+
+
+## [1.4.2] - 2017-03-20
+
+### Fixed
+
+- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing
calls to `trigger_error` when deprecated methods are invoked.
-## 1.4.1 - 2017-02-27
-* Reverted BC break by reintroducing behavior to automagically fix a URI with a
+## [1.4.1] - 2017-02-27
+
+### Added
+
+- Rriggering of silenced deprecation warnings.
+
+### Fixed
+
+- Reverted BC break by reintroducing behavior to automagically fix a URI with a
relative path and an authority by adding a leading slash to the path. It's only
deprecated now.
-* Added triggering of silenced deprecation warnings.
-## 1.4.0 - 2017-02-21
-* Fix `Stream::read` when length parameter <= 0.
-* `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.
-* Fix `ServerRequest::getUriFromGlobals` when `Host` header contains port.
-* Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.
-* Allow `parse_response` to parse a response without delimiting space and reason.
-* Ensure each URI modification results in a valid URI according to PSR-7 discussions.
- Invalid modifications will throw an exception instead of returning a wrong URI or
- doing some magic.
- - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception
- because the path of a URI with an authority must start with a slash "/" or be empty
- - `(new Uri())->withScheme('http')` will return `'http://localhost'`
-* Fix compatibility of URIs with `file` scheme and empty host.
-* Added common URI utility methods based on RFC 3986 (see documentation in the readme):
+## [1.4.0] - 2017-02-21
+
+### Added
+
+- Added common URI utility methods based on RFC 3986 (see documentation in the readme):
- `Uri::isDefaultPort`
- `Uri::isAbsolute`
- `Uri::isNetworkPathReference`
@@ -37,69 +87,117 @@
- `UriNormalizer::normalize`
- `UriNormalizer::isEquivalent`
- `UriResolver::relativize`
-* Deprecated `Uri::resolve` in favor of `UriResolver::resolve`
-* Deprecated `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`
-## 1.3.1 - 2016-06-25
+### Changed
+
+- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.
+- Allow `parse_response` to parse a response without delimiting space and reason.
+- Ensure each URI modification results in a valid URI according to PSR-7 discussions.
+ Invalid modifications will throw an exception instead of returning a wrong URI or
+ doing some magic.
+ - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception
+ because the path of a URI with an authority must start with a slash "/" or be empty
+ - `(new Uri())->withScheme('http')` will return `'http://localhost'`
+
+### Deprecated
+
+- `Uri::resolve` in favor of `UriResolver::resolve`
+- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`
+
+### Fixed
+
+- `Stream::read` when length parameter <= 0.
+- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.
+- `ServerRequest::getUriFromGlobals` when `Host` header contains port.
+- Compatibility of URIs with `file` scheme and empty host.
+
-* Fix `Uri::__toString` for network path references, e.g. `//example.org`.
-* Fix missing lowercase normalization for host.
-* Fix handling of URI components in case they are `'0'` in a lot of places,
+## [1.3.1] - 2016-06-25
+
+### Fixed
+
+- `Uri::__toString` for network path references, e.g. `//example.org`.
+- Missing lowercase normalization for host.
+- Handling of URI components in case they are `'0'` in a lot of places,
e.g. as a user info password.
-* Fix `Uri::withAddedHeader` to correctly merge headers with different case.
-* Fix trimming of header values in `Uri::withAddedHeader`. Header values may
+- `Uri::withAddedHeader` to correctly merge headers with different case.
+- Trimming of header values in `Uri::withAddedHeader`. Header values may
be surrounded by whitespace which should be ignored according to RFC 7230
Section 3.2.4. This does not apply to header names.
-* Fix `Uri::withAddedHeader` with an array of header values.
-* Fix `Uri::resolve` when base path has no slash and handling of fragment.
-* Fix handling of encoding in `Uri::with(out)QueryValue` so one can pass the
+- `Uri::withAddedHeader` with an array of header values.
+- `Uri::resolve` when base path has no slash and handling of fragment.
+- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the
key/value both in encoded as well as decoded form to those methods. This is
consistent with withPath, withQuery etc.
-* Fix `ServerRequest::withoutAttribute` when attribute value is null.
+- `ServerRequest::withoutAttribute` when attribute value is null.
+
+
+## [1.3.0] - 2016-04-13
-## 1.3.0 - 2016-04-13
+### Added
-* Added remaining interfaces needed for full PSR7 compatibility
+- Remaining interfaces needed for full PSR7 compatibility
(ServerRequestInterface, UploadedFileInterface, etc.).
-* Added support for stream_for from scalars.
-* Can now extend Uri.
-* Fixed a bug in validating request methods by making it more permissive.
+- Support for stream_for from scalars.
-## 1.2.3 - 2016-02-18
+### Changed
-* Fixed support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
+- Can now extend Uri.
+
+### Fixed
+- A bug in validating request methods by making it more permissive.
+
+
+## [1.2.3] - 2016-02-18
+
+### Fixed
+
+- Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
streams, which can sometimes return fewer bytes than requested with `fread`.
-* Fixed handling of gzipped responses with FNAME headers.
+- Handling of gzipped responses with FNAME headers.
+
+
+## [1.2.2] - 2016-01-22
+
+### Added
+
+- Support for URIs without any authority.
+- Support for HTTP 451 'Unavailable For Legal Reasons.'
+- Support for using '0' as a filename.
+- Support for including non-standard ports in Host headers.
-## 1.2.2 - 2016-01-22
-* Added support for URIs without any authority.
-* Added support for HTTP 451 'Unavailable For Legal Reasons.'
-* Added support for using '0' as a filename.
-* Added support for including non-standard ports in Host headers.
+## [1.2.1] - 2015-11-02
-## 1.2.1 - 2015-11-02
+### Changes
-* Now supporting negative offsets when seeking to SEEK_END.
+- Now supporting negative offsets when seeking to SEEK_END.
-## 1.2.0 - 2015-08-15
-* Body as `"0"` is now properly added to a response.
-* Now allowing forward seeking in CachingStream.
-* Now properly parsing HTTP requests that contain proxy targets in
+## [1.2.0] - 2015-08-15
+
+### Changed
+
+- Body as `"0"` is now properly added to a response.
+- Now allowing forward seeking in CachingStream.
+- Now properly parsing HTTP requests that contain proxy targets in
`parse_request`.
-* functions.php is now conditionally required.
-* user-info is no longer dropped when resolving URIs.
+- functions.php is now conditionally required.
+- user-info is no longer dropped when resolving URIs.
+
+
+## [1.1.0] - 2015-06-24
-## 1.1.0 - 2015-06-24
+### Changed
-* URIs can now be relative.
-* `multipart/form-data` headers are now overridden case-insensitively.
-* URI paths no longer encode the following characters because they are allowed
+- URIs can now be relative.
+- `multipart/form-data` headers are now overridden case-insensitively.
+- URI paths no longer encode the following characters because they are allowed
in URIs: "(", ")", "*", "!", "'"
-* A port is no longer added to a URI when the scheme is missing and no port is
+- A port is no longer added to a URI when the scheme is missing and no port is
present.
+
## 1.0.0 - 2015-05-19
Initial release.
@@ -108,3 +206,20 @@ Currently unsupported:
- `Psr\Http\Message\ServerRequestInterface`
- `Psr\Http\Message\UploadedFileInterface`
+
+
+
+[Unreleased]: https://github.com/guzzle/psr7/compare/1.5.2...HEAD
+[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2
+[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1
+[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0
+[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2
+[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1
+[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0
+[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1
+[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0
+[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3
+[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2
+[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1
+[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0
+[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0
diff --git a/guzzlehttp/psr7/README.md b/guzzlehttp/psr7/README.md
index 16499358..c60a6a38 100644
--- a/guzzlehttp/psr7/README.md
+++ b/guzzlehttp/psr7/README.md
@@ -372,7 +372,7 @@ This method accepts the following `$resource` types:
$stream = GuzzleHttp\Psr7\stream_for('foo');
$stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r'));
-$generator function ($bytes) {
+$generator = function ($bytes) {
for ($i = 0; $i < $bytes; $i++) {
yield ' ';
}
@@ -606,6 +606,12 @@ Creates a new URI with a specific query string value. Any existing query string
provided key are removed and replaced with the given key value pair. A value of null will set the query string
key without a value, e.g. "key" instead of "key=value".
+### `GuzzleHttp\Psr7\Uri::withQueryValues`
+
+`public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface`
+
+Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an
+associative array of key => value.
### `GuzzleHttp\Psr7\Uri::withoutQueryValue`
diff --git a/guzzlehttp/psr7/composer.json b/guzzlehttp/psr7/composer.json
index b1c5a90b..2add153e 100644
--- a/guzzlehttp/psr7/composer.json
+++ b/guzzlehttp/psr7/composer.json
@@ -2,7 +2,7 @@
"name": "guzzlehttp/psr7",
"type": "library",
"description": "PSR-7 message implementation that also provides common utility methods",
- "keywords": ["request", "response", "message", "stream", "http", "uri", "url"],
+ "keywords": ["request", "response", "message", "stream", "http", "uri", "url", "psr-7"],
"license": "MIT",
"authors": [
{
@@ -17,10 +17,11 @@
],
"require": {
"php": ">=5.4.0",
- "psr/http-message": "~1.0"
+ "psr/http-message": "~1.0",
+ "ralouphie/getallheaders": "^2.0.5"
},
"require-dev": {
- "phpunit/phpunit": "~4.0"
+ "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"provide": {
"psr/http-message-implementation": "1.0"
@@ -31,9 +32,14 @@
},
"files": ["src/functions_include.php"]
},
+ "autoload-dev": {
+ "psr-4": {
+ "GuzzleHttp\\Tests\\Psr7\\": "tests/"
+ }
+ },
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "1.5-dev"
}
}
}
diff --git a/guzzlehttp/psr7/src/AppendStream.php b/guzzlehttp/psr7/src/AppendStream.php
index 23039fd7..472a0d61 100644
--- a/guzzlehttp/psr7/src/AppendStream.php
+++ b/guzzlehttp/psr7/src/AppendStream.php
@@ -16,7 +16,6 @@ class AppendStream implements StreamInterface
private $seekable = true;
private $current = 0;
private $pos = 0;
- private $detached = false;
/**
* @param StreamInterface[] $streams Streams to decorate. Each stream must
@@ -73,6 +72,7 @@ class AppendStream implements StreamInterface
public function close()
{
$this->pos = $this->current = 0;
+ $this->seekable = true;
foreach ($this->streams as $stream) {
$stream->close();
@@ -82,14 +82,22 @@ class AppendStream implements StreamInterface
}
/**
- * Detaches each attached stream
+ * Detaches each attached stream.
+ *
+ * Returns null as it's not clear which underlying stream resource to return.
*
* {@inheritdoc}
*/
public function detach()
{
- $this->close();
- $this->detached = true;
+ $this->pos = $this->current = 0;
+ $this->seekable = true;
+
+ foreach ($this->streams as $stream) {
+ $stream->detach();
+ }
+
+ $this->streams = [];
}
public function tell()
diff --git a/guzzlehttp/psr7/src/FnStream.php b/guzzlehttp/psr7/src/FnStream.php
index cc9b4453..73daea6f 100644
--- a/guzzlehttp/psr7/src/FnStream.php
+++ b/guzzlehttp/psr7/src/FnStream.php
@@ -53,6 +53,15 @@ class FnStream implements StreamInterface
}
/**
+ * An unserialize would allow the __destruct to run when the unserialized value goes out of scope.
+ * @throws \LogicException
+ */
+ public function __wakeup()
+ {
+ throw new \LogicException('FnStream should never be unserialized');
+ }
+
+ /**
* Adds custom functionality to an underlying stream by intercepting
* specific method calls.
*
diff --git a/guzzlehttp/psr7/src/InflateStream.php b/guzzlehttp/psr7/src/InflateStream.php
index 0051d3fe..5e4f6028 100644
--- a/guzzlehttp/psr7/src/InflateStream.php
+++ b/guzzlehttp/psr7/src/InflateStream.php
@@ -27,7 +27,7 @@ class InflateStream implements StreamInterface
$stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength);
$resource = StreamWrapper::getResource($stream);
stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
- $this->stream = new Stream($resource);
+ $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource));
}
/**
diff --git a/guzzlehttp/psr7/src/Request.php b/guzzlehttp/psr7/src/Request.php
index 08285484..00066424 100644
--- a/guzzlehttp/psr7/src/Request.php
+++ b/guzzlehttp/psr7/src/Request.php
@@ -45,7 +45,7 @@ class Request implements RequestInterface
$this->setHeaders($headers);
$this->protocol = $version;
- if (!$this->hasHeader('Host')) {
+ if (!isset($this->headerNames['host'])) {
$this->updateHostFromUri();
}
@@ -110,7 +110,7 @@ class Request implements RequestInterface
$new = clone $this;
$new->uri = $uri;
- if (!$preserveHost) {
+ if (!$preserveHost || !isset($this->headerNames['host'])) {
$new->updateHostFromUri();
}
diff --git a/guzzlehttp/psr7/src/Response.php b/guzzlehttp/psr7/src/Response.php
index 2830c6c9..6e72c06b 100644
--- a/guzzlehttp/psr7/src/Response.php
+++ b/guzzlehttp/psr7/src/Response.php
@@ -93,6 +93,10 @@ class Response implements ResponseInterface
$version = '1.1',
$reason = null
) {
+ if (filter_var($status, FILTER_VALIDATE_INT) === false) {
+ throw new \InvalidArgumentException('Status code must be an integer value.');
+ }
+
$this->statusCode = (int) $status;
if ($body !== '' && $body !== null) {
diff --git a/guzzlehttp/psr7/src/Rfc7230.php b/guzzlehttp/psr7/src/Rfc7230.php
new file mode 100644
index 00000000..505e4742
--- /dev/null
+++ b/guzzlehttp/psr7/src/Rfc7230.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace GuzzleHttp\Psr7;
+
+final class Rfc7230
+{
+ /**
+ * Header related regular expressions (copied from amphp/http package)
+ * (Note: once we require PHP 7.x we could just depend on the upstream package)
+ *
+ * Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons.
+ *
+ * @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15
+ * @license https://github.com/amphp/http/blob/v1.0.1/LICENSE
+ */
+ const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m";
+ const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)";
+}
diff --git a/guzzlehttp/psr7/src/ServerRequest.php b/guzzlehttp/psr7/src/ServerRequest.php
index 575aab84..99f453a5 100644
--- a/guzzlehttp/psr7/src/ServerRequest.php
+++ b/guzzlehttp/psr7/src/ServerRequest.php
@@ -166,7 +166,7 @@ class ServerRequest extends Request implements ServerRequestInterface
public static function fromGlobals()
{
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
- $headers = function_exists('getallheaders') ? getallheaders() : [];
+ $headers = getallheaders();
$uri = self::getUriFromGlobals();
$body = new LazyOpenStream('php://input', 'r+');
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
@@ -180,23 +180,41 @@ class ServerRequest extends Request implements ServerRequestInterface
->withUploadedFiles(self::normalizeFiles($_FILES));
}
+ private static function extractHostAndPortFromAuthority($authority)
+ {
+ $uri = 'http://'.$authority;
+ $parts = parse_url($uri);
+ if (false === $parts) {
+ return [null, null];
+ }
+
+ $host = isset($parts['host']) ? $parts['host'] : null;
+ $port = isset($parts['port']) ? $parts['port'] : null;
+
+ return [$host, $port];
+ }
+
/**
* Get a Uri populated with values from $_SERVER.
*
* @return UriInterface
*/
- public static function getUriFromGlobals() {
+ public static function getUriFromGlobals()
+ {
$uri = new Uri('');
$uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
$hasPort = false;
if (isset($_SERVER['HTTP_HOST'])) {
- $hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']);
- $uri = $uri->withHost($hostHeaderParts[0]);
- if (isset($hostHeaderParts[1])) {
+ list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
+ if ($host !== null) {
+ $uri = $uri->withHost($host);
+ }
+
+ if ($port !== null) {
$hasPort = true;
- $uri = $uri->withPort($hostHeaderParts[1]);
+ $uri = $uri->withPort($port);
}
} elseif (isset($_SERVER['SERVER_NAME'])) {
$uri = $uri->withHost($_SERVER['SERVER_NAME']);
@@ -210,7 +228,7 @@ class ServerRequest extends Request implements ServerRequestInterface
$hasQuery = false;
if (isset($_SERVER['REQUEST_URI'])) {
- $requestUriParts = explode('?', $_SERVER['REQUEST_URI']);
+ $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2);
$uri = $uri->withPath($requestUriParts[0]);
if (isset($requestUriParts[1])) {
$hasQuery = true;
diff --git a/guzzlehttp/psr7/src/Stream.php b/guzzlehttp/psr7/src/Stream.php
index e3366287..111795eb 100644
--- a/guzzlehttp/psr7/src/Stream.php
+++ b/guzzlehttp/psr7/src/Stream.php
@@ -24,11 +24,11 @@ class Stream implements StreamInterface
'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
- 'x+t' => true, 'c+t' => true, 'a+' => true
+ 'x+t' => true, 'c+t' => true, 'a+' => true, 'rb+' => true,
],
'write' => [
'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
- 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
+ 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, 'rb+' => true,
'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
]
@@ -70,15 +70,6 @@ class Stream implements StreamInterface
$this->uri = $this->getMetadata('uri');
}
- public function __get($name)
- {
- if ($name == 'stream') {
- throw new \RuntimeException('The stream is detached');
- }
-
- throw new \BadMethodCallException('No value for ' . $name);
- }
-
/**
* Closes the stream when the destructed
*/
@@ -99,6 +90,10 @@ class Stream implements StreamInterface
public function getContents()
{
+ if (!isset($this->stream)) {
+ throw new \RuntimeException('Stream is detached');
+ }
+
$contents = stream_get_contents($this->stream);
if ($contents === false) {
@@ -173,11 +168,19 @@ class Stream implements StreamInterface
public function eof()
{
- return !$this->stream || feof($this->stream);
+ if (!isset($this->stream)) {
+ throw new \RuntimeException('Stream is detached');
+ }
+
+ return feof($this->stream);
}
public function tell()
{
+ if (!isset($this->stream)) {
+ throw new \RuntimeException('Stream is detached');
+ }
+
$result = ftell($this->stream);
if ($result === false) {
@@ -194,9 +197,13 @@ class Stream implements StreamInterface
public function seek($offset, $whence = SEEK_SET)
{
+ if (!isset($this->stream)) {
+ throw new \RuntimeException('Stream is detached');
+ }
if (!$this->seekable) {
throw new \RuntimeException('Stream is not seekable');
- } elseif (fseek($this->stream, $offset, $whence) === -1) {
+ }
+ if (fseek($this->stream, $offset, $whence) === -1) {
throw new \RuntimeException('Unable to seek to stream position '
. $offset . ' with whence ' . var_export($whence, true));
}
@@ -204,6 +211,9 @@ class Stream implements StreamInterface
public function read($length)
{
+ if (!isset($this->stream)) {
+ throw new \RuntimeException('Stream is detached');
+ }
if (!$this->readable) {
throw new \RuntimeException('Cannot read from non-readable stream');
}
@@ -225,6 +235,9 @@ class Stream implements StreamInterface
public function write($string)
{
+ if (!isset($this->stream)) {
+ throw new \RuntimeException('Stream is detached');
+ }
if (!$this->writable) {
throw new \RuntimeException('Cannot write to a non-writable stream');
}
diff --git a/guzzlehttp/psr7/src/StreamWrapper.php b/guzzlehttp/psr7/src/StreamWrapper.php
index cf7b2232..0f3a2856 100644
--- a/guzzlehttp/psr7/src/StreamWrapper.php
+++ b/guzzlehttp/psr7/src/StreamWrapper.php
@@ -38,9 +38,21 @@ class StreamWrapper
. 'writable, or both.');
}
- return fopen('guzzle://stream', $mode, null, stream_context_create([
+ return fopen('guzzle://stream', $mode, null, self::createStreamContext($stream));
+ }
+
+ /**
+ * Creates a stream context that can be used to open a stream as a php stream resource.
+ *
+ * @param StreamInterface $stream
+ *
+ * @return resource
+ */
+ public static function createStreamContext(StreamInterface $stream)
+ {
+ return stream_context_create([
'guzzle' => ['stream' => $stream]
- ]));
+ ]);
}
/**
@@ -94,12 +106,21 @@ class StreamWrapper
return true;
}
+ public function stream_cast($cast_as)
+ {
+ $stream = clone($this->stream);
+
+ return $stream->detach();
+ }
+
public function stream_stat()
{
static $modeMap = [
'r' => 33060,
+ 'rb' => 33060,
'r+' => 33206,
- 'w' => 33188
+ 'w' => 33188,
+ 'wb' => 33188
];
return [
@@ -118,4 +139,23 @@ class StreamWrapper
'blocks' => 0
];
}
+
+ public function url_stat($path, $flags)
+ {
+ return [
+ 'dev' => 0,
+ 'ino' => 0,
+ 'mode' => 0,
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 0,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ 'blksize' => 0,
+ 'blocks' => 0
+ ];
+ }
}
diff --git a/guzzlehttp/psr7/src/Uri.php b/guzzlehttp/psr7/src/Uri.php
index f46c1db9..36219568 100644
--- a/guzzlehttp/psr7/src/Uri.php
+++ b/guzzlehttp/psr7/src/Uri.php
@@ -301,15 +301,7 @@ class Uri implements UriInterface
*/
public static function withoutQueryValue(UriInterface $uri, $key)
{
- $current = $uri->getQuery();
- if ($current === '') {
- return $uri;
- }
-
- $decodedKey = rawurldecode($key);
- $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
- return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
- });
+ $result = self::getFilteredQueryString($uri, [$key]);
return $uri->withQuery(implode('&', $result));
}
@@ -331,26 +323,29 @@ class Uri implements UriInterface
*/
public static function withQueryValue(UriInterface $uri, $key, $value)
{
- $current = $uri->getQuery();
+ $result = self::getFilteredQueryString($uri, [$key]);
- if ($current === '') {
- $result = [];
- } else {
- $decodedKey = rawurldecode($key);
- $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
- return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
- });
- }
+ $result[] = self::generateQueryString($key, $value);
- // Query string separators ("=", "&") within the key or value need to be encoded
- // (while preventing double-encoding) before setting the query string. All other
- // chars that need percent-encoding will be encoded by withQuery().
- $key = strtr($key, self::$replaceQuery);
+ return $uri->withQuery(implode('&', $result));
+ }
- if ($value !== null) {
- $result[] = $key . '=' . strtr($value, self::$replaceQuery);
- } else {
- $result[] = $key;
+ /**
+ * Creates a new URI with multiple specific query string values.
+ *
+ * It has the same behavior as withQueryValue() but for an associative array of key => value.
+ *
+ * @param UriInterface $uri URI to use as a base.
+ * @param array $keyValueArray Associative array of key and values
+ *
+ * @return UriInterface
+ */
+ public static function withQueryValues(UriInterface $uri, array $keyValueArray)
+ {
+ $result = self::getFilteredQueryString($uri, array_keys($keyValueArray));
+
+ foreach ($keyValueArray as $key => $value) {
+ $result[] = self::generateQueryString($key, $value);
}
return $uri->withQuery(implode('&', $result));
@@ -620,6 +615,47 @@ class Uri implements UriInterface
return $port;
}
+ /**
+ * @param UriInterface $uri
+ * @param array $keys
+ *
+ * @return array
+ */
+ private static function getFilteredQueryString(UriInterface $uri, array $keys)
+ {
+ $current = $uri->getQuery();
+
+ if ($current === '') {
+ return [];
+ }
+
+ $decodedKeys = array_map('rawurldecode', $keys);
+
+ return array_filter(explode('&', $current), function ($part) use ($decodedKeys) {
+ return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true);
+ });
+ }
+
+ /**
+ * @param string $key
+ * @param string|null $value
+ *
+ * @return string
+ */
+ private static function generateQueryString($key, $value)
+ {
+ // Query string separators ("=", "&") within the key or value need to be encoded
+ // (while preventing double-encoding) before setting the query string. All other
+ // chars that need percent-encoding will be encoded by withQuery().
+ $queryString = strtr($key, self::$replaceQuery);
+
+ if ($value !== null) {
+ $queryString .= '=' . strtr($value, self::$replaceQuery);
+ }
+
+ return $queryString;
+ }
+
private function removeDefaultPort()
{
if ($this->port !== null && self::isDefaultPort($this)) {
diff --git a/guzzlehttp/psr7/src/functions.php b/guzzlehttp/psr7/src/functions.php
index e40348d6..957bfb42 100644
--- a/guzzlehttp/psr7/src/functions.php
+++ b/guzzlehttp/psr7/src/functions.php
@@ -69,10 +69,10 @@ function uri_for($uri)
* - metadata: Array of custom metadata.
* - size: Size of the stream.
*
- * @param resource|string|null|int|float|bool|StreamInterface|callable $resource Entity body data
- * @param array $options Additional options
+ * @param resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource Entity body data
+ * @param array $options Additional options
*
- * @return Stream
+ * @return StreamInterface
* @throws \InvalidArgumentException if the $resource arg is not valid.
*/
function stream_for($resource = '', array $options = [])
@@ -238,7 +238,7 @@ function modify_request(RequestInterface $request, array $changes)
}
if ($request instanceof ServerRequestInterface) {
- return new ServerRequest(
+ return (new ServerRequest(
isset($changes['method']) ? $changes['method'] : $request->getMethod(),
$uri,
$headers,
@@ -247,7 +247,11 @@ function modify_request(RequestInterface $request, array $changes)
? $changes['version']
: $request->getProtocolVersion(),
$request->getServerParams()
- );
+ ))
+ ->withParsedBody($request->getParsedBody())
+ ->withQueryParams($request->getQueryParams())
+ ->withCookieParams($request->getCookieParams())
+ ->withUploadedFiles($request->getUploadedFiles());
}
return new Request(
@@ -431,7 +435,7 @@ function hash(
* @param StreamInterface $stream Stream to read from
* @param int $maxLength Maximum buffer length
*
- * @return string|bool
+ * @return string
*/
function readline(StreamInterface $stream, $maxLength = null)
{
@@ -495,7 +499,7 @@ function parse_response($message)
// between status-code and reason-phrase is required. But browsers accept
// responses without space and reason as well.
if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
- throw new \InvalidArgumentException('Invalid response string');
+ throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
}
$parts = explode(' ', $data['start-line'], 3);
@@ -516,8 +520,8 @@ function parse_response($message)
* PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
* be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
*
- * @param string $str Query string to parse
- * @param bool|string $urlEncoding How the query string is encoded
+ * @param string $str Query string to parse
+ * @param int|bool $urlEncoding How the query string is encoded
*
* @return array
*/
@@ -533,9 +537,9 @@ function parse_query($str, $urlEncoding = true)
$decoder = function ($value) {
return rawurldecode(str_replace('+', ' ', $value));
};
- } elseif ($urlEncoding == PHP_QUERY_RFC3986) {
+ } elseif ($urlEncoding === PHP_QUERY_RFC3986) {
$decoder = 'rawurldecode';
- } elseif ($urlEncoding == PHP_QUERY_RFC1738) {
+ } elseif ($urlEncoding === PHP_QUERY_RFC1738) {
$decoder = 'urldecode';
} else {
$decoder = function ($str) { return $str; };
@@ -633,6 +637,7 @@ function mimetype_from_filename($filename)
function mimetype_from_extension($extension)
{
static $mimetypes = [
+ '3gp' => 'video/3gpp',
'7z' => 'application/x-7z-compressed',
'aac' => 'audio/x-aac',
'ai' => 'application/postscript',
@@ -680,6 +685,7 @@ function mimetype_from_extension($extension)
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mov' => 'video/quicktime',
+ 'mkv' => 'video/x-matroska',
'mp3' => 'audio/mpeg',
'mp4' => 'video/mp4',
'mp4a' => 'audio/mp4',
@@ -758,29 +764,53 @@ function _parse_message($message)
throw new \InvalidArgumentException('Invalid message');
}
- // Iterate over each line in the message, accounting for line endings
- $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
- $result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => ''];
- array_shift($lines);
+ $message = ltrim($message, "\r\n");
- for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
- $line = $lines[$i];
- // If two line breaks were encountered, then this is the end of body
- if (empty($line)) {
- if ($i < $totalLines - 1) {
- $result['body'] = implode('', array_slice($lines, $i + 2));
- }
- break;
- }
- if (strpos($line, ':')) {
- $parts = explode(':', $line, 2);
- $key = trim($parts[0]);
- $value = isset($parts[1]) ? trim($parts[1]) : '';
- $result['headers'][$key][] = $value;
+ $messageParts = preg_split("/\r?\n\r?\n/", $message, 2);
+
+ if ($messageParts === false || count($messageParts) !== 2) {
+ throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
+ }
+
+ list($rawHeaders, $body) = $messageParts;
+ $rawHeaders .= "\r\n"; // Put back the delimiter we split previously
+ $headerParts = preg_split("/\r?\n/", $rawHeaders, 2);
+
+ if ($headerParts === false || count($headerParts) !== 2) {
+ throw new \InvalidArgumentException('Invalid message: Missing status line');
+ }
+
+ list($startLine, $rawHeaders) = $headerParts;
+
+ if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
+ // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
+ $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
+ }
+
+ /** @var array[] $headerLines */
+ $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER);
+
+ // If these aren't the same, then one line didn't match and there's an invalid header.
+ if ($count !== substr_count($rawHeaders, "\n")) {
+ // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4
+ if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {
+ throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding');
}
+
+ throw new \InvalidArgumentException('Invalid header syntax');
}
- return $result;
+ $headers = [];
+
+ foreach ($headerLines as $headerLine) {
+ $headers[$headerLine[1]][] = $headerLine[2];
+ }
+
+ return [
+ 'start-line' => $startLine,
+ 'headers' => $headers,
+ 'body' => $body,
+ ];
}
/**
@@ -809,6 +839,46 @@ function _parse_request_uri($path, array $headers)
return $scheme . '://' . $host . '/' . ltrim($path, '/');
}
+/**
+ * Get a short summary of the message body
+ *
+ * Will return `null` if the response is not printable.
+ *
+ * @param MessageInterface $message The message to get the body summary
+ * @param int $truncateAt The maximum allowed size of the summary
+ *
+ * @return null|string
+ */
+function get_message_body_summary(MessageInterface $message, $truncateAt = 120)
+{
+ $body = $message->getBody();
+
+ if (!$body->isSeekable() || !$body->isReadable()) {
+ return null;
+ }
+
+ $size = $body->getSize();
+
+ if ($size === 0) {
+ return null;
+ }
+
+ $summary = $body->read($truncateAt);
+ $body->rewind();
+
+ if ($size > $truncateAt) {
+ $summary .= ' (truncated...)';
+ }
+
+ // Matches any printable character, including unicode characters:
+ // letters, marks, numbers, punctuation, spacing, and separators.
+ if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
+ return null;
+ }
+
+ return $summary;
+}
+
/** @internal */
function _caseless_remove($keys, array $data)
{