first commit
This commit is contained in:
1
libraries/vendor/laminas/laminas-diactoros/COPYRIGHT.md
vendored
Normal file
1
libraries/vendor/laminas/laminas-diactoros/COPYRIGHT.md
vendored
Normal file
@ -0,0 +1 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
|
||||
26
libraries/vendor/laminas/laminas-diactoros/LICENSE.md
vendored
Normal file
26
libraries/vendor/laminas/laminas-diactoros/LICENSE.md
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
148
libraries/vendor/laminas/laminas-diactoros/src/AbstractSerializer.php
vendored
Normal file
148
libraries/vendor/laminas/laminas-diactoros/src/AbstractSerializer.php
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function array_pop;
|
||||
use function implode;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function trim;
|
||||
use function ucwords;
|
||||
|
||||
/**
|
||||
* Provides base functionality for request and response de/serialization
|
||||
* strategies, including functionality for retrieving a line at a time from
|
||||
* the message, splitting headers from the body, and serializing headers.
|
||||
*/
|
||||
abstract class AbstractSerializer
|
||||
{
|
||||
public const CR = "\r";
|
||||
public const EOL = "\r\n";
|
||||
public const LF = "\n";
|
||||
|
||||
/**
|
||||
* Retrieve a single line from the stream.
|
||||
*
|
||||
* Retrieves a line from the stream; a line is defined as a sequence of
|
||||
* characters ending in a CRLF sequence.
|
||||
*
|
||||
* @throws Exception\DeserializationException If the sequence contains a CR
|
||||
* or LF in isolation, or ends in a CR.
|
||||
*/
|
||||
protected static function getLine(StreamInterface $stream): string
|
||||
{
|
||||
$line = '';
|
||||
$crFound = false;
|
||||
while (! $stream->eof()) {
|
||||
$char = $stream->read(1);
|
||||
|
||||
if ($crFound && $char === self::LF) {
|
||||
$crFound = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// CR NOT followed by LF
|
||||
if ($crFound && $char !== self::LF) {
|
||||
throw Exception\DeserializationException::forUnexpectedCarriageReturn();
|
||||
}
|
||||
|
||||
// LF in isolation
|
||||
if (! $crFound && $char === self::LF) {
|
||||
throw Exception\DeserializationException::forUnexpectedLineFeed();
|
||||
}
|
||||
|
||||
// CR found; do not append
|
||||
if ($char === self::CR) {
|
||||
$crFound = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Any other character: append
|
||||
$line .= $char;
|
||||
}
|
||||
|
||||
// CR found at end of stream
|
||||
if ($crFound) {
|
||||
throw Exception\DeserializationException::forUnexpectedEndOfHeaders();
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the stream into headers and body content.
|
||||
*
|
||||
* Returns an array containing two elements
|
||||
*
|
||||
* - The first is an array of headers
|
||||
* - The second is a StreamInterface containing the body content
|
||||
*
|
||||
* @throws Exception\DeserializationException For invalid headers.
|
||||
*/
|
||||
protected static function splitStream(StreamInterface $stream): array
|
||||
{
|
||||
$headers = [];
|
||||
$currentHeader = false;
|
||||
|
||||
while ($line = self::getLine($stream)) {
|
||||
if (preg_match(';^(?P<name>[!#$%&\'*+.^_`\|~0-9a-zA-Z-]+):(?P<value>.*)$;', $line, $matches)) {
|
||||
$currentHeader = $matches['name'];
|
||||
if (! isset($headers[$currentHeader])) {
|
||||
$headers[$currentHeader] = [];
|
||||
}
|
||||
$headers[$currentHeader][] = trim($matches['value'], "\t ");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $currentHeader) {
|
||||
throw Exception\DeserializationException::forInvalidHeader();
|
||||
}
|
||||
|
||||
if (! preg_match('#^[ \t]#', $line)) {
|
||||
throw Exception\DeserializationException::forInvalidHeaderContinuation();
|
||||
}
|
||||
|
||||
// Append continuation to last header value found
|
||||
$value = array_pop($headers[$currentHeader]);
|
||||
$headers[$currentHeader][] = $value . ' ' . trim($line, "\t ");
|
||||
}
|
||||
|
||||
// use RelativeStream to avoid copying initial stream into memory
|
||||
return [$headers, new RelativeStream($stream, $stream->tell())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize headers to string values.
|
||||
*
|
||||
* @psalm-param array<string, string[]> $headers
|
||||
*/
|
||||
protected static function serializeHeaders(array $headers): string
|
||||
{
|
||||
$lines = [];
|
||||
foreach ($headers as $header => $values) {
|
||||
$normalized = self::filterHeader($header);
|
||||
foreach ($values as $value) {
|
||||
$lines[] = sprintf('%s: %s', $normalized, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\r\n", $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a header name to wordcase
|
||||
*
|
||||
* @param string $header
|
||||
*/
|
||||
protected static function filterHeader($header): string
|
||||
{
|
||||
$filtered = str_replace('-', ' ', $header);
|
||||
$filtered = ucwords($filtered);
|
||||
return str_replace(' ', '-', $filtered);
|
||||
}
|
||||
}
|
||||
181
libraries/vendor/laminas/laminas-diactoros/src/CallbackStream.php
vendored
Normal file
181
libraries/vendor/laminas/laminas-diactoros/src/CallbackStream.php
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Stringable;
|
||||
|
||||
use function array_key_exists;
|
||||
|
||||
use const SEEK_SET;
|
||||
|
||||
/**
|
||||
* Implementation of PSR HTTP streams
|
||||
*/
|
||||
class CallbackStream implements StreamInterface, Stringable
|
||||
{
|
||||
/** @var callable|null */
|
||||
protected $callback;
|
||||
|
||||
/**
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function __construct(callable $callback)
|
||||
{
|
||||
$this->attach($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->getContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
$this->callback = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return null|callable
|
||||
*/
|
||||
public function detach(): ?callable
|
||||
{
|
||||
$callback = $this->callback;
|
||||
$this->callback = null;
|
||||
return $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a new callback to the instance.
|
||||
*/
|
||||
public function attach(callable $callback): void
|
||||
{
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize(): ?int
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function tell(): int
|
||||
{
|
||||
throw Exception\UntellableStreamException::forCallbackStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function eof(): bool
|
||||
{
|
||||
return empty($this->callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isSeekable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $whence
|
||||
* @return void
|
||||
*/
|
||||
public function seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
throw Exception\UnseekableStreamException::forCallbackStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rewind(): void
|
||||
{
|
||||
throw Exception\UnrewindableStreamException::forCallbackStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isWritable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($string): void
|
||||
{
|
||||
throw Exception\UnwritableStreamException::forCallbackStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isReadable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($length): string
|
||||
{
|
||||
throw Exception\UnreadableStreamException::forCallbackStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContents(): string
|
||||
{
|
||||
$callback = $this->detach();
|
||||
$contents = $callback ? $callback() : '';
|
||||
return (string) $contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
$metadata = [
|
||||
'eof' => $this->eof(),
|
||||
'stream_type' => 'callback',
|
||||
'seekable' => false,
|
||||
];
|
||||
|
||||
if (null === $key) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
if (! array_key_exists($key, $metadata)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $metadata[$key];
|
||||
}
|
||||
}
|
||||
63
libraries/vendor/laminas/laminas-diactoros/src/ConfigProvider.php
vendored
Normal file
63
libraries/vendor/laminas/laminas-diactoros/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
use Psr\Http\Message\ResponseFactoryInterface;
|
||||
use Psr\Http\Message\ServerRequestFactoryInterface;
|
||||
use Psr\Http\Message\StreamFactoryInterface;
|
||||
use Psr\Http\Message\UploadedFileFactoryInterface;
|
||||
use Psr\Http\Message\UriFactoryInterface;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public const CONFIG_KEY = 'laminas-diactoros';
|
||||
public const X_FORWARDED = 'x-forwarded-request-filter';
|
||||
public const X_FORWARDED_TRUSTED_PROXIES = 'trusted-proxies';
|
||||
public const X_FORWARDED_TRUSTED_HEADERS = 'trusted-headers';
|
||||
|
||||
/**
|
||||
* Retrieve configuration for laminas-diactoros.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => $this->getDependencies(),
|
||||
self::CONFIG_KEY => $this->getComponentConfig(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the container dependencies.
|
||||
* Maps factory interfaces to factories.
|
||||
*/
|
||||
public function getDependencies(): array
|
||||
{
|
||||
// @codingStandardsIgnoreStart
|
||||
return [
|
||||
'invokables' => [
|
||||
RequestFactoryInterface::class => RequestFactory::class,
|
||||
ResponseFactoryInterface::class => ResponseFactory::class,
|
||||
StreamFactoryInterface::class => StreamFactory::class,
|
||||
ServerRequestFactoryInterface::class => ServerRequestFactory::class,
|
||||
UploadedFileFactoryInterface::class => UploadedFileFactory::class,
|
||||
UriFactoryInterface::class => UriFactory::class
|
||||
],
|
||||
];
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
public function getComponentConfig(): array
|
||||
{
|
||||
return [
|
||||
self::X_FORWARDED => [
|
||||
self::X_FORWARDED_TRUSTED_PROXIES => '',
|
||||
self::X_FORWARDED_TRUSTED_HEADERS => [],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
46
libraries/vendor/laminas/laminas-diactoros/src/Exception/DeserializationException.php
vendored
Normal file
46
libraries/vendor/laminas/laminas-diactoros/src/Exception/DeserializationException.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use Throwable;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class DeserializationException extends UnexpectedValueException implements ExceptionInterface
|
||||
{
|
||||
public static function forInvalidHeader(): self
|
||||
{
|
||||
throw new self('Invalid header detected');
|
||||
}
|
||||
|
||||
public static function forInvalidHeaderContinuation(): self
|
||||
{
|
||||
throw new self('Invalid header continuation');
|
||||
}
|
||||
|
||||
public static function forRequestFromArray(Throwable $previous): self
|
||||
{
|
||||
return new self('Cannot deserialize request', $previous->getCode(), $previous);
|
||||
}
|
||||
|
||||
public static function forResponseFromArray(Throwable $previous): self
|
||||
{
|
||||
return new self('Cannot deserialize response', $previous->getCode(), $previous);
|
||||
}
|
||||
|
||||
public static function forUnexpectedCarriageReturn(): self
|
||||
{
|
||||
throw new self('Unexpected carriage return detected');
|
||||
}
|
||||
|
||||
public static function forUnexpectedEndOfHeaders(): self
|
||||
{
|
||||
throw new self('Unexpected end of headers');
|
||||
}
|
||||
|
||||
public static function forUnexpectedLineFeed(): self
|
||||
{
|
||||
throw new self('Unexpected line feed detected');
|
||||
}
|
||||
}
|
||||
14
libraries/vendor/laminas/laminas-diactoros/src/Exception/ExceptionInterface.php
vendored
Normal file
14
libraries/vendor/laminas/laminas-diactoros/src/Exception/ExceptionInterface.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Marker interface for package-specific exceptions.
|
||||
*/
|
||||
interface ExceptionInterface extends Throwable
|
||||
{
|
||||
}
|
||||
9
libraries/vendor/laminas/laminas-diactoros/src/Exception/InvalidArgumentException.php
vendored
Normal file
9
libraries/vendor/laminas/laminas-diactoros/src/Exception/InvalidArgumentException.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
28
libraries/vendor/laminas/laminas-diactoros/src/Exception/InvalidForwardedHeaderNameException.php
vendored
Normal file
28
libraries/vendor/laminas/laminas-diactoros/src/Exception/InvalidForwardedHeaderNameException.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders;
|
||||
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
class InvalidForwardedHeaderNameException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function forHeader(mixed $name): self
|
||||
{
|
||||
if (! is_string($name)) {
|
||||
$name = sprintf('(value of type %s)', is_object($name) ? $name::class : gettype($name));
|
||||
}
|
||||
|
||||
return new self(sprintf(
|
||||
'Invalid X-Forwarded-* header name "%s" provided to %s',
|
||||
$name,
|
||||
FilterUsingXForwardedHeaders::class
|
||||
));
|
||||
}
|
||||
}
|
||||
32
libraries/vendor/laminas/laminas-diactoros/src/Exception/InvalidProxyAddressException.php
vendored
Normal file
32
libraries/vendor/laminas/laminas-diactoros/src/Exception/InvalidProxyAddressException.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function sprintf;
|
||||
|
||||
class InvalidProxyAddressException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function forInvalidProxyArgument(mixed $proxy): self
|
||||
{
|
||||
$type = is_object($proxy) ? $proxy::class : gettype($proxy);
|
||||
return new self(sprintf(
|
||||
'Invalid proxy of type "%s" provided;'
|
||||
. ' must be a valid IPv4 or IPv6 address, optionally with a subnet mask provided'
|
||||
. ' or an array of such values',
|
||||
$type,
|
||||
));
|
||||
}
|
||||
|
||||
public static function forAddress(string $address): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Invalid proxy address "%s" provided;'
|
||||
. ' must be a valid IPv4 or IPv6 address, optionally with a subnet mask provided',
|
||||
$address,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
class InvalidStreamPointerPositionException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
/** {@inheritDoc} */
|
||||
public function __construct(
|
||||
string $message = 'Invalid pointer position',
|
||||
int $code = 0,
|
||||
?Throwable $previous = null
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
9
libraries/vendor/laminas/laminas-diactoros/src/Exception/RuntimeException.php
vendored
Normal file
9
libraries/vendor/laminas/laminas-diactoros/src/Exception/RuntimeException.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
20
libraries/vendor/laminas/laminas-diactoros/src/Exception/SerializationException.php
vendored
Normal file
20
libraries/vendor/laminas/laminas-diactoros/src/Exception/SerializationException.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use UnexpectedValueException;
|
||||
|
||||
class SerializationException extends UnexpectedValueException implements ExceptionInterface
|
||||
{
|
||||
public static function forInvalidRequestLine(): self
|
||||
{
|
||||
return new self('Invalid request line detected');
|
||||
}
|
||||
|
||||
public static function forInvalidStatusLine(): self
|
||||
{
|
||||
return new self('No status line detected');
|
||||
}
|
||||
}
|
||||
30
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnreadableStreamException.php
vendored
Normal file
30
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnreadableStreamException.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class UnreadableStreamException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function dueToConfiguration(): self
|
||||
{
|
||||
return new self('Stream is not readable');
|
||||
}
|
||||
|
||||
public static function dueToMissingResource(): self
|
||||
{
|
||||
return new self('No resource available; cannot read');
|
||||
}
|
||||
|
||||
public static function dueToPhpError(): self
|
||||
{
|
||||
return new self('Error reading stream');
|
||||
}
|
||||
|
||||
public static function forCallbackStream(): self
|
||||
{
|
||||
return new self('Callback streams cannot read');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class UnrecognizedProtocolVersionException extends UnexpectedValueException implements ExceptionInterface
|
||||
{
|
||||
public static function forVersion(string $version): self
|
||||
{
|
||||
return new self(sprintf('Unrecognized protocol version (%s)', $version));
|
||||
}
|
||||
}
|
||||
15
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnrewindableStreamException.php
vendored
Normal file
15
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnrewindableStreamException.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class UnrewindableStreamException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function forCallbackStream(): self
|
||||
{
|
||||
return new self('Callback streams cannot rewind position');
|
||||
}
|
||||
}
|
||||
30
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnseekableStreamException.php
vendored
Normal file
30
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnseekableStreamException.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class UnseekableStreamException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function dueToConfiguration(): self
|
||||
{
|
||||
return new self('Stream is not seekable');
|
||||
}
|
||||
|
||||
public static function dueToMissingResource(): self
|
||||
{
|
||||
return new self('No resource available; cannot seek position');
|
||||
}
|
||||
|
||||
public static function dueToPhpError(): self
|
||||
{
|
||||
return new self('Error seeking within stream');
|
||||
}
|
||||
|
||||
public static function forCallbackStream(): self
|
||||
{
|
||||
return new self('Callback streams cannot seek position');
|
||||
}
|
||||
}
|
||||
25
libraries/vendor/laminas/laminas-diactoros/src/Exception/UntellableStreamException.php
vendored
Normal file
25
libraries/vendor/laminas/laminas-diactoros/src/Exception/UntellableStreamException.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class UntellableStreamException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function dueToMissingResource(): self
|
||||
{
|
||||
return new self('No resource available; cannot tell position');
|
||||
}
|
||||
|
||||
public static function dueToPhpError(): self
|
||||
{
|
||||
return new self('Error occurred during tell operation');
|
||||
}
|
||||
|
||||
public static function forCallbackStream(): self
|
||||
{
|
||||
return new self('Callback streams cannot tell position');
|
||||
}
|
||||
}
|
||||
30
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnwritableStreamException.php
vendored
Normal file
30
libraries/vendor/laminas/laminas-diactoros/src/Exception/UnwritableStreamException.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class UnwritableStreamException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function dueToConfiguration(): self
|
||||
{
|
||||
return new self('Stream is not writable');
|
||||
}
|
||||
|
||||
public static function dueToMissingResource(): self
|
||||
{
|
||||
return new self('No resource available; cannot write');
|
||||
}
|
||||
|
||||
public static function dueToPhpError(): self
|
||||
{
|
||||
return new self('Error writing to stream');
|
||||
}
|
||||
|
||||
public static function forCallbackStream(): self
|
||||
{
|
||||
return new self('Callback streams cannot write');
|
||||
}
|
||||
}
|
||||
20
libraries/vendor/laminas/laminas-diactoros/src/Exception/UploadedFileAlreadyMovedException.php
vendored
Normal file
20
libraries/vendor/laminas/laminas-diactoros/src/Exception/UploadedFileAlreadyMovedException.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
class UploadedFileAlreadyMovedException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
/** {@inheritDoc} */
|
||||
public function __construct(
|
||||
string $message = 'Cannot retrieve stream after it has already moved',
|
||||
int $code = 0,
|
||||
?Throwable $previous = null
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
38
libraries/vendor/laminas/laminas-diactoros/src/Exception/UploadedFileErrorException.php
vendored
Normal file
38
libraries/vendor/laminas/laminas-diactoros/src/Exception/UploadedFileErrorException.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class UploadedFileErrorException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
public static function forUnmovableFile(): self
|
||||
{
|
||||
return new self('Error occurred while moving uploaded file');
|
||||
}
|
||||
|
||||
public static function dueToStreamUploadError(string $error): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Cannot retrieve stream due to upload error: %s',
|
||||
$error
|
||||
));
|
||||
}
|
||||
|
||||
public static function dueToUnwritablePath(): self
|
||||
{
|
||||
return new self('Unable to write to designated path');
|
||||
}
|
||||
|
||||
public static function dueToUnwritableTarget(string $targetDirectory): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The target directory `%s` does not exist or is not writable',
|
||||
$targetDirectory
|
||||
));
|
||||
}
|
||||
}
|
||||
164
libraries/vendor/laminas/laminas-diactoros/src/HeaderSecurity.php
vendored
Normal file
164
libraries/vendor/laminas/laminas-diactoros/src/HeaderSecurity.php
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use function gettype;
|
||||
use function in_array;
|
||||
use function is_numeric;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function ord;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* Provide security tools around HTTP headers to prevent common injection vectors.
|
||||
*/
|
||||
final class HeaderSecurity
|
||||
{
|
||||
/**
|
||||
* Private constructor; non-instantiable.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a header value
|
||||
*
|
||||
* Ensures CRLF header injection vectors are filtered.
|
||||
*
|
||||
* Per RFC 7230, only VISIBLE ASCII characters, spaces, and horizontal
|
||||
* tabs are allowed in values; header continuations MUST consist of
|
||||
* a single CRLF sequence followed by a space or horizontal tab.
|
||||
*
|
||||
* This method filters any values not allowed from the string, and is
|
||||
* lossy.
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/HTTP_response_splitting
|
||||
*/
|
||||
public static function filter(string $value): string
|
||||
{
|
||||
$length = strlen($value);
|
||||
$string = '';
|
||||
for ($i = 0; $i < $length; $i += 1) {
|
||||
$ascii = ord($value[$i]);
|
||||
|
||||
// Detect continuation sequences
|
||||
if ($ascii === 13) {
|
||||
$lf = ord($value[$i + 1]);
|
||||
$ws = ord($value[$i + 2]);
|
||||
if ($lf === 10 && in_array($ws, [9, 32], true)) {
|
||||
$string .= $value[$i] . $value[$i + 1];
|
||||
$i += 1;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Non-visible, non-whitespace characters
|
||||
// 9 === horizontal tab
|
||||
// 32-126, 128-254 === visible
|
||||
// 127 === DEL
|
||||
// 255 === null byte
|
||||
if (
|
||||
($ascii < 32 && $ascii !== 9)
|
||||
|| $ascii === 127
|
||||
|| $ascii > 254
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$string .= $value[$i];
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a header value.
|
||||
*
|
||||
* Per RFC 7230, only VISIBLE ASCII characters, spaces, and horizontal
|
||||
* tabs are allowed in values; header continuations MUST consist of
|
||||
* a single CRLF sequence followed by a space or horizontal tab.
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/HTTP_response_splitting
|
||||
*
|
||||
* @param string|int|float $value
|
||||
*/
|
||||
public static function isValid($value): bool
|
||||
{
|
||||
$value = (string) $value;
|
||||
|
||||
// Look for:
|
||||
// \n not preceded by \r, OR
|
||||
// \r not followed by \n, OR
|
||||
// \r\n not followed by space or horizontal tab; these are all CRLF attacks
|
||||
if (preg_match("#(?:(?:(?<!\r)\n)|(?:\r(?!\n))|(?:\r\n(?![ \t])))#", $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Non-visible, non-whitespace characters
|
||||
// 9 === horizontal tab
|
||||
// 10 === line feed
|
||||
// 13 === carriage return
|
||||
// 32-126, 128-254 === visible
|
||||
// 127 === DEL (disallowed)
|
||||
// 255 === null byte (disallowed)
|
||||
if (preg_match('/[^\x09\x0a\x0d\x20-\x7E\x80-\xFE]/', $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a header value is valid.
|
||||
*
|
||||
* @param mixed $value Value to be tested. This method asserts it is a string or number.
|
||||
* @throws Exception\InvalidArgumentException For invalid values.
|
||||
*/
|
||||
public static function assertValid(mixed $value): void
|
||||
{
|
||||
if (! is_string($value) && ! is_numeric($value)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Invalid header value type; must be a string or numeric; received %s',
|
||||
is_object($value) ? $value::class : gettype($value)
|
||||
));
|
||||
}
|
||||
if (! self::isValid($value)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'"%s" is not valid header value',
|
||||
$value
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether or not a header name is valid.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc7230#section-3.2
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public static function assertValidName(mixed $name): void
|
||||
{
|
||||
if (! is_string($name)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Invalid header name type; expected string; received %s',
|
||||
is_object($name) ? $name::class : gettype($name)
|
||||
));
|
||||
}
|
||||
if (! preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $name)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'"%s" is not valid header name',
|
||||
$name
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
414
libraries/vendor/laminas/laminas-diactoros/src/MessageTrait.php
vendored
Normal file
414
libraries/vendor/laminas/laminas-diactoros/src/MessageTrait.php
vendored
Normal file
@ -0,0 +1,414 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\MessageInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function array_values;
|
||||
use function gettype;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function strtolower;
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
* Trait implementing the various methods defined in MessageInterface.
|
||||
*
|
||||
* @see https://github.com/php-fig/http-message/tree/master/src/MessageInterface.php
|
||||
*/
|
||||
trait MessageTrait
|
||||
{
|
||||
/**
|
||||
* List of all registered headers, as key => array of values.
|
||||
*
|
||||
* @var array
|
||||
* @psalm-var array<non-empty-string, list<string>>
|
||||
*/
|
||||
protected $headers = [];
|
||||
|
||||
/**
|
||||
* Map of normalized header name to original name used to register header.
|
||||
*
|
||||
* @var array
|
||||
* @psalm-var array<non-empty-string, non-empty-string>
|
||||
*/
|
||||
protected $headerNames = [];
|
||||
|
||||
/** @var string */
|
||||
private $protocol = '1.1';
|
||||
|
||||
/** @var StreamInterface */
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* Retrieves the HTTP protocol version as a string.
|
||||
*
|
||||
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
|
||||
*
|
||||
* @return string HTTP protocol version.
|
||||
*/
|
||||
public function getProtocolVersion(): string
|
||||
{
|
||||
return $this->protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified HTTP protocol version.
|
||||
*
|
||||
* The version string MUST contain only the HTTP version number (e.g.,
|
||||
* "1.1", "1.0").
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new protocol version.
|
||||
*
|
||||
* @param string $version HTTP protocol version
|
||||
* @return static
|
||||
*/
|
||||
public function withProtocolVersion($version): MessageInterface
|
||||
{
|
||||
$this->validateProtocolVersion($version);
|
||||
$new = clone $this;
|
||||
$new->protocol = $version;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all message headers.
|
||||
*
|
||||
* The keys represent the header name as it will be sent over the wire, and
|
||||
* each value is an array of strings associated with the header.
|
||||
*
|
||||
* // Represent the headers as a string
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* echo $name . ": " . implode(", ", $values);
|
||||
* }
|
||||
*
|
||||
* // Emit headers iteratively:
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* foreach ($values as $value) {
|
||||
* header(sprintf('%s: %s', $name, $value), false);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @return array Returns an associative array of the message's headers. Each
|
||||
* key MUST be a header name, and each value MUST be an array of strings.
|
||||
* @psalm-return array<non-empty-string, list<string>>
|
||||
*/
|
||||
public function getHeaders(): array
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a header exists by the given case-insensitive name.
|
||||
*
|
||||
* @param string $header Case-insensitive header name.
|
||||
* @return bool Returns true if any header names match the given header
|
||||
* name using a case-insensitive string comparison. Returns false if
|
||||
* no matching header name is found in the message.
|
||||
*/
|
||||
public function hasHeader($header): bool
|
||||
{
|
||||
return isset($this->headerNames[strtolower($header)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a message header value by the given case-insensitive name.
|
||||
*
|
||||
* This method returns an array of all the header values of the given
|
||||
* case-insensitive header name.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return an
|
||||
* empty array.
|
||||
*
|
||||
* @param string $header Case-insensitive header field name.
|
||||
* @return string[] An array of string values as provided for the given
|
||||
* header. If the header does not appear in the message, this method MUST
|
||||
* return an empty array.
|
||||
*/
|
||||
public function getHeader($header): array
|
||||
{
|
||||
if (! $this->hasHeader($header)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$header = $this->headerNames[strtolower($header)];
|
||||
|
||||
return $this->headers[$header];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a comma-separated string of the values for a single header.
|
||||
*
|
||||
* This method returns all of the header values of the given
|
||||
* case-insensitive header name as a string concatenated together using
|
||||
* a comma.
|
||||
*
|
||||
* NOTE: Not all header values may be appropriately represented using
|
||||
* comma concatenation. For such headers, use getHeader() instead
|
||||
* and supply your own delimiter when concatenating.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return
|
||||
* an empty string.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return string A string of values as provided for the given header
|
||||
* concatenated together using a comma. If the header does not appear in
|
||||
* the message, this method MUST return an empty string.
|
||||
*/
|
||||
public function getHeaderLine($name): string
|
||||
{
|
||||
$value = $this->getHeader($name);
|
||||
if (empty($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return implode(',', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the provided header, replacing any existing
|
||||
* values of any headers with the same case-insensitive name.
|
||||
*
|
||||
* While header names are case-insensitive, the casing of the header will
|
||||
* be preserved by this function, and returned from getHeaders().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new and/or updated header and value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws Exception\InvalidArgumentException For invalid header names or values.
|
||||
*/
|
||||
public function withHeader($name, $value): MessageInterface
|
||||
{
|
||||
$this->assertHeader($name);
|
||||
|
||||
$normalized = strtolower($name);
|
||||
|
||||
$new = clone $this;
|
||||
if ($new->hasHeader($name)) {
|
||||
unset($new->headers[$new->headerNames[$normalized]]);
|
||||
}
|
||||
|
||||
$value = $this->filterHeaderValue($value);
|
||||
|
||||
$new->headerNames[$normalized] = $name;
|
||||
$new->headers[$name] = $value;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified header appended with the
|
||||
* given value.
|
||||
*
|
||||
* Existing values for the specified header will be maintained. The new
|
||||
* value(s) will be appended to the existing list. If the header did not
|
||||
* exist previously, it will be added.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new header and/or value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to add.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws Exception\InvalidArgumentException For invalid header names or values.
|
||||
*/
|
||||
public function withAddedHeader($name, $value): MessageInterface
|
||||
{
|
||||
$this->assertHeader($name);
|
||||
|
||||
if (! $this->hasHeader($name)) {
|
||||
return $this->withHeader($name, $value);
|
||||
}
|
||||
|
||||
$header = $this->headerNames[strtolower($name)];
|
||||
|
||||
$new = clone $this;
|
||||
$value = $this->filterHeaderValue($value);
|
||||
$new->headers[$header] = array_merge($this->headers[$header], $value);
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance without the specified header.
|
||||
*
|
||||
* Header resolution MUST be done without case-sensitivity.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that removes
|
||||
* the named header.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to remove.
|
||||
* @return static
|
||||
*/
|
||||
public function withoutHeader($name): MessageInterface
|
||||
{
|
||||
if (! is_string($name) || $name === '' || ! $this->hasHeader($name)) {
|
||||
return clone $this;
|
||||
}
|
||||
|
||||
$normalized = strtolower($name);
|
||||
$original = $this->headerNames[$normalized];
|
||||
|
||||
$new = clone $this;
|
||||
unset($new->headers[$original], $new->headerNames[$normalized]);
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the body of the message.
|
||||
*
|
||||
* @return StreamInterface Returns the body as a stream.
|
||||
*/
|
||||
public function getBody(): StreamInterface
|
||||
{
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified message body.
|
||||
*
|
||||
* The body MUST be a StreamInterface object.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return a new instance that has the
|
||||
* new body stream.
|
||||
*
|
||||
* @param StreamInterface $body Body.
|
||||
* @return static
|
||||
* @throws Exception\InvalidArgumentException When the body is not valid.
|
||||
*/
|
||||
public function withBody(StreamInterface $body): MessageInterface
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->stream = $body;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/** @param StreamInterface|string|resource $stream */
|
||||
private function getStream($stream, string $modeIfNotInstance): StreamInterface
|
||||
{
|
||||
if ($stream instanceof StreamInterface) {
|
||||
return $stream;
|
||||
}
|
||||
|
||||
if (! is_string($stream) && ! is_resource($stream)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Stream must be a string stream resource identifier, '
|
||||
. 'an actual stream resource, '
|
||||
. 'or a Psr\Http\Message\StreamInterface implementation'
|
||||
);
|
||||
}
|
||||
|
||||
return new Stream($stream, $modeIfNotInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a set of headers to ensure they are in the correct internal format.
|
||||
*
|
||||
* Used by message constructors to allow setting all initial headers at once.
|
||||
*
|
||||
* @param array $originalHeaders Headers to filter.
|
||||
*/
|
||||
private function setHeaders(array $originalHeaders): void
|
||||
{
|
||||
$headerNames = $headers = [];
|
||||
|
||||
foreach ($originalHeaders as $header => $value) {
|
||||
$value = $this->filterHeaderValue($value);
|
||||
|
||||
$this->assertHeader($header);
|
||||
|
||||
$headerNames[strtolower($header)] = $header;
|
||||
$headers[$header] = $value;
|
||||
}
|
||||
|
||||
$this->headerNames = $headerNames;
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the HTTP protocol version
|
||||
*
|
||||
* @param string $version
|
||||
* @throws Exception\InvalidArgumentException On invalid HTTP protocol version.
|
||||
*/
|
||||
private function validateProtocolVersion($version): void
|
||||
{
|
||||
if (empty($version)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'HTTP protocol version can not be empty'
|
||||
);
|
||||
}
|
||||
if (! is_string($version)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Unsupported HTTP protocol version; must be a string, received %s',
|
||||
is_object($version) ? $version::class : gettype($version)
|
||||
));
|
||||
}
|
||||
|
||||
// HTTP/1 uses a "<major>.<minor>" numbering scheme to indicate
|
||||
// versions of the protocol, while HTTP/2 does not.
|
||||
if (! preg_match('#^(1\.[01]|2(\.0)?)$#', $version)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Unsupported HTTP protocol version "%s" provided',
|
||||
$version
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
private function filterHeaderValue(mixed $values): array
|
||||
{
|
||||
if (! is_array($values)) {
|
||||
$values = [$values];
|
||||
}
|
||||
|
||||
if ([] === $values) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid header value: must be a string or array of strings; '
|
||||
. 'cannot be an empty array'
|
||||
);
|
||||
}
|
||||
|
||||
return array_map(static function ($value): string {
|
||||
HeaderSecurity::assertValid($value);
|
||||
|
||||
$value = (string) $value;
|
||||
|
||||
// Normalize line folding to a single space (RFC 7230#3.2.4).
|
||||
$value = str_replace(["\r\n\t", "\r\n "], ' ', $value);
|
||||
|
||||
// Remove optional whitespace (OWS, RFC 7230#3.2.3) around the header value.
|
||||
return trim($value, "\t ");
|
||||
}, array_values($values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure header name and values are valid.
|
||||
*
|
||||
* @param string $name
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
private function assertHeader($name): void
|
||||
{
|
||||
HeaderSecurity::assertValidName($name);
|
||||
}
|
||||
}
|
||||
15
libraries/vendor/laminas/laminas-diactoros/src/Module.php
vendored
Normal file
15
libraries/vendor/laminas/laminas-diactoros/src/Module.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
class Module
|
||||
{
|
||||
public function getConfig(): array
|
||||
{
|
||||
return [
|
||||
'service_manager' => (new ConfigProvider())->getDependencies(),
|
||||
];
|
||||
}
|
||||
}
|
||||
84
libraries/vendor/laminas/laminas-diactoros/src/PhpInputStream.php
vendored
Normal file
84
libraries/vendor/laminas/laminas-diactoros/src/PhpInputStream.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Stringable;
|
||||
|
||||
use function stream_get_contents;
|
||||
|
||||
/**
|
||||
* Caching version of php://input
|
||||
*/
|
||||
class PhpInputStream extends Stream implements Stringable
|
||||
{
|
||||
private string $cache = '';
|
||||
|
||||
private bool $reachedEof = false;
|
||||
|
||||
/**
|
||||
* @param string|resource $stream
|
||||
*/
|
||||
public function __construct($stream = 'php://input')
|
||||
{
|
||||
parent::__construct($stream, 'r');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
if ($this->reachedEof) {
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
$this->getContents();
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isWritable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($length): string
|
||||
{
|
||||
$content = parent::read($length);
|
||||
if (! $this->reachedEof) {
|
||||
$this->cache .= $content;
|
||||
}
|
||||
|
||||
if ($this->eof()) {
|
||||
$this->reachedEof = true;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContents($maxLength = -1): string
|
||||
{
|
||||
if ($this->reachedEof) {
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
$contents = stream_get_contents($this->resource, $maxLength);
|
||||
$this->cache .= $contents;
|
||||
|
||||
if ($maxLength === -1 || $this->eof()) {
|
||||
$this->reachedEof = true;
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
}
|
||||
162
libraries/vendor/laminas/laminas-diactoros/src/RelativeStream.php
vendored
Normal file
162
libraries/vendor/laminas/laminas-diactoros/src/RelativeStream.php
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Stringable;
|
||||
|
||||
use const SEEK_SET;
|
||||
|
||||
/**
|
||||
* Wrapper for default Stream class, representing subpart (starting from given offset) of initial stream.
|
||||
* It can be used to avoid copying full stream, conserving memory.
|
||||
*
|
||||
* @see AbstractSerializer::splitStream()
|
||||
*/
|
||||
final class RelativeStream implements StreamInterface, Stringable
|
||||
{
|
||||
private int $offset;
|
||||
|
||||
public function __construct(private StreamInterface $decoratedStream, ?int $offset)
|
||||
{
|
||||
$this->offset = (int) $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
if ($this->isSeekable()) {
|
||||
$this->seek(0);
|
||||
}
|
||||
return $this->getContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
$this->decoratedStream->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function detach()
|
||||
{
|
||||
return $this->decoratedStream->detach();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize(): int
|
||||
{
|
||||
return $this->decoratedStream->getSize() - $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function tell(): int
|
||||
{
|
||||
return $this->decoratedStream->tell() - $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function eof(): bool
|
||||
{
|
||||
return $this->decoratedStream->eof();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isSeekable(): bool
|
||||
{
|
||||
return $this->decoratedStream->isSeekable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function seek($offset, $whence = SEEK_SET): void
|
||||
{
|
||||
if ($whence === SEEK_SET) {
|
||||
$this->decoratedStream->seek($offset + $this->offset, $whence);
|
||||
return;
|
||||
}
|
||||
$this->decoratedStream->seek($offset, $whence);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rewind(): void
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isWritable(): bool
|
||||
{
|
||||
return $this->decoratedStream->isWritable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($string): int
|
||||
{
|
||||
if ($this->tell() < 0) {
|
||||
throw new Exception\InvalidStreamPointerPositionException();
|
||||
}
|
||||
return $this->decoratedStream->write($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isReadable(): bool
|
||||
{
|
||||
return $this->decoratedStream->isReadable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($length): string
|
||||
{
|
||||
if ($this->tell() < 0) {
|
||||
throw new Exception\InvalidStreamPointerPositionException();
|
||||
}
|
||||
return $this->decoratedStream->read($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContents(): string
|
||||
{
|
||||
if ($this->tell() < 0) {
|
||||
throw new Exception\InvalidStreamPointerPositionException();
|
||||
}
|
||||
return $this->decoratedStream->getContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
return $this->decoratedStream->getMetadata($key);
|
||||
}
|
||||
}
|
||||
72
libraries/vendor/laminas/laminas-diactoros/src/Request.php
vendored
Normal file
72
libraries/vendor/laminas/laminas-diactoros/src/Request.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* HTTP Request encapsulation
|
||||
*
|
||||
* Requests are considered immutable; all methods that might change state are
|
||||
* implemented such that they retain the internal state of the current
|
||||
* message and return a new instance that contains the changed state.
|
||||
*/
|
||||
class Request implements RequestInterface
|
||||
{
|
||||
use RequestTrait;
|
||||
|
||||
/**
|
||||
* @param null|string|UriInterface $uri URI for the request, if any.
|
||||
* @param null|string $method HTTP method for the request, if any.
|
||||
* @param string|resource|StreamInterface $body Message body, if any.
|
||||
* @param array $headers Headers for the message, if any.
|
||||
* @throws Exception\InvalidArgumentException For any invalid value.
|
||||
*/
|
||||
public function __construct($uri = null, ?string $method = null, $body = 'php://temp', array $headers = [])
|
||||
{
|
||||
$this->initialize($uri, $method, $body, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHeaders(): array
|
||||
{
|
||||
$headers = $this->headers;
|
||||
if (
|
||||
! $this->hasHeader('host')
|
||||
&& $this->uri->getHost()
|
||||
) {
|
||||
$headers['Host'] = [$this->getHostFromUri()];
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHeader($name): array
|
||||
{
|
||||
if (empty($name) || ! $this->hasHeader($name)) {
|
||||
if (
|
||||
strtolower($name) === 'host'
|
||||
&& $this->uri->getHost()
|
||||
) {
|
||||
return [$this->getHostFromUri()];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$header = $this->headerNames[strtolower($name)];
|
||||
|
||||
return $this->headers[$header];
|
||||
}
|
||||
}
|
||||
86
libraries/vendor/laminas/laminas-diactoros/src/Request/ArraySerializer.php
vendored
Normal file
86
libraries/vendor/laminas/laminas-diactoros/src/Request/ArraySerializer.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Request;
|
||||
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Request;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Throwable;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Serialize or deserialize request messages to/from arrays.
|
||||
*
|
||||
* This class provides functionality for serializing a RequestInterface instance
|
||||
* to an array, as well as the reverse operation of creating a Request instance
|
||||
* from an array representing a message.
|
||||
*/
|
||||
final class ArraySerializer
|
||||
{
|
||||
/**
|
||||
* Serialize a request message to an array.
|
||||
*
|
||||
* @return array{
|
||||
* method: string,
|
||||
* request_target: string,
|
||||
* uri: string,
|
||||
* protocol_version: string,
|
||||
* headers: array<array<string>>,
|
||||
* body: string
|
||||
* }
|
||||
*/
|
||||
public static function toArray(RequestInterface $request): array
|
||||
{
|
||||
return [
|
||||
'method' => $request->getMethod(),
|
||||
'request_target' => $request->getRequestTarget(),
|
||||
'uri' => (string) $request->getUri(),
|
||||
'protocol_version' => $request->getProtocolVersion(),
|
||||
'headers' => $request->getHeaders(),
|
||||
'body' => (string) $request->getBody(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a request array to a request instance.
|
||||
*
|
||||
* @throws Exception\DeserializationException When the response cannot be deserialized.
|
||||
*/
|
||||
public static function fromArray(array $serializedRequest): Request
|
||||
{
|
||||
try {
|
||||
$uri = self::getValueFromKey($serializedRequest, 'uri');
|
||||
$method = self::getValueFromKey($serializedRequest, 'method');
|
||||
$body = new Stream('php://memory', 'wb+');
|
||||
$body->write(self::getValueFromKey($serializedRequest, 'body'));
|
||||
$headers = self::getValueFromKey($serializedRequest, 'headers');
|
||||
$requestTarget = self::getValueFromKey($serializedRequest, 'request_target');
|
||||
$protocolVersion = self::getValueFromKey($serializedRequest, 'protocol_version');
|
||||
|
||||
return (new Request($uri, $method, $body, $headers))
|
||||
->withRequestTarget($requestTarget)
|
||||
->withProtocolVersion($protocolVersion);
|
||||
} catch (Throwable $exception) {
|
||||
throw Exception\DeserializationException::forRequestFromArray($exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception\DeserializationException
|
||||
*/
|
||||
private static function getValueFromKey(array $data, string $key, ?string $message = null)
|
||||
{
|
||||
if (isset($data[$key])) {
|
||||
return $data[$key];
|
||||
}
|
||||
if ($message === null) {
|
||||
$message = sprintf('Missing "%s" key in serialized request', $key);
|
||||
}
|
||||
throw new Exception\DeserializationException($message);
|
||||
}
|
||||
}
|
||||
137
libraries/vendor/laminas/laminas-diactoros/src/Request/Serializer.php
vendored
Normal file
137
libraries/vendor/laminas/laminas-diactoros/src/Request/Serializer.php
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Request;
|
||||
|
||||
use Laminas\Diactoros\AbstractSerializer;
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Request;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use Laminas\Diactoros\Uri;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Serialize (cast to string) or deserialize (cast string to Request) messages.
|
||||
*
|
||||
* This class provides functionality for serializing a RequestInterface instance
|
||||
* to a string, as well as the reverse operation of creating a Request instance
|
||||
* from a string/stream representing a message.
|
||||
*/
|
||||
final class Serializer extends AbstractSerializer
|
||||
{
|
||||
/**
|
||||
* Deserialize a request string to a request instance.
|
||||
*
|
||||
* Internally, casts the message to a stream and invokes fromStream().
|
||||
*
|
||||
* @throws Exception\SerializationException When errors occur parsing the message.
|
||||
*/
|
||||
public static function fromString(string $message): Request
|
||||
{
|
||||
$stream = new Stream('php://temp', 'wb+');
|
||||
$stream->write($message);
|
||||
return self::fromStream($stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a request stream to a request instance.
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException If the message stream is not readable or seekable.
|
||||
* @throws Exception\SerializationException If an invalid request line is detected.
|
||||
*/
|
||||
public static function fromStream(StreamInterface $stream): Request
|
||||
{
|
||||
if (! $stream->isReadable() || ! $stream->isSeekable()) {
|
||||
throw new Exception\InvalidArgumentException('Message stream must be both readable and seekable');
|
||||
}
|
||||
|
||||
$stream->rewind();
|
||||
|
||||
[$method, $requestTarget, $version] = self::getRequestLine($stream);
|
||||
$uri = self::createUriFromRequestTarget($requestTarget);
|
||||
|
||||
[$headers, $body] = self::splitStream($stream);
|
||||
|
||||
return (new Request($uri, $method, $body, $headers))
|
||||
->withProtocolVersion($version)
|
||||
->withRequestTarget($requestTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a request message to a string.
|
||||
*/
|
||||
public static function toString(RequestInterface $request): string
|
||||
{
|
||||
$httpMethod = $request->getMethod();
|
||||
$headers = self::serializeHeaders($request->getHeaders());
|
||||
$body = (string) $request->getBody();
|
||||
$format = '%s %s HTTP/%s%s%s';
|
||||
|
||||
if (! empty($headers)) {
|
||||
$headers = "\r\n" . $headers;
|
||||
}
|
||||
if (! empty($body)) {
|
||||
$headers .= "\r\n\r\n";
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
$format,
|
||||
$httpMethod,
|
||||
$request->getRequestTarget(),
|
||||
$request->getProtocolVersion(),
|
||||
$headers,
|
||||
$body
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the components of the request line.
|
||||
*
|
||||
* Retrieves the first line of the stream and parses it, raising an
|
||||
* exception if it does not follow specifications; if valid, returns a list
|
||||
* with the method, target, and version, in that order.
|
||||
*
|
||||
* @throws Exception\SerializationException
|
||||
*/
|
||||
private static function getRequestLine(StreamInterface $stream): array
|
||||
{
|
||||
$requestLine = self::getLine($stream);
|
||||
|
||||
if (
|
||||
! preg_match(
|
||||
'#^(?P<method>[!\#$%&\'*+.^_`|~a-zA-Z0-9-]+) (?P<target>[^\s]+) HTTP/(?P<version>[1-9]\d*\.\d+)$#',
|
||||
$requestLine,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
throw Exception\SerializationException::forInvalidRequestLine();
|
||||
}
|
||||
|
||||
return [$matches['method'], $matches['target'], $matches['version']];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a Uri instance based on the provided request target.
|
||||
*
|
||||
* If the request target is of authority or asterisk form, an empty Uri
|
||||
* instance is returned; otherwise, the value is used to create and return
|
||||
* a new Uri instance.
|
||||
*/
|
||||
private static function createUriFromRequestTarget(string $requestTarget): Uri
|
||||
{
|
||||
if (preg_match('#^https?://#', $requestTarget)) {
|
||||
return new Uri($requestTarget);
|
||||
}
|
||||
|
||||
if (preg_match('#^(\*|[^/])#', $requestTarget)) {
|
||||
return new Uri();
|
||||
}
|
||||
|
||||
return new Uri($requestTarget);
|
||||
}
|
||||
}
|
||||
19
libraries/vendor/laminas/laminas-diactoros/src/RequestFactory.php
vendored
Normal file
19
libraries/vendor/laminas/laminas-diactoros/src/RequestFactory.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
class RequestFactory implements RequestFactoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createRequest(string $method, $uri): RequestInterface
|
||||
{
|
||||
return new Request($uri, $method);
|
||||
}
|
||||
}
|
||||
315
libraries/vendor/laminas/laminas-diactoros/src/RequestTrait.php
vendored
Normal file
315
libraries/vendor/laminas/laminas-diactoros/src/RequestTrait.php
vendored
Normal file
@ -0,0 +1,315 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
use function array_keys;
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* Trait with common request behaviors.
|
||||
*
|
||||
* Server and client-side requests differ slightly in how the Host header is
|
||||
* handled; on client-side, it should be calculated on-the-fly from the
|
||||
* composed URI (if present), while on server-side, it will be calculated from
|
||||
* the environment. As such, this trait exists to provide the common code
|
||||
* between both client-side and server-side requests, and each can then
|
||||
* use the headers functionality required by their implementations.
|
||||
*/
|
||||
trait RequestTrait
|
||||
{
|
||||
use MessageTrait;
|
||||
|
||||
/** @var string */
|
||||
private $method = 'GET';
|
||||
|
||||
/**
|
||||
* The request-target, if it has been provided or calculated.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
private $requestTarget;
|
||||
|
||||
/** @var UriInterface */
|
||||
private $uri;
|
||||
|
||||
/**
|
||||
* Initialize request state.
|
||||
*
|
||||
* Used by constructors.
|
||||
*
|
||||
* @param null|string|UriInterface $uri URI for the request, if any.
|
||||
* @param null|string $method HTTP method for the request, if any.
|
||||
* @param string|resource|StreamInterface $body Message body, if any.
|
||||
* @param array $headers Headers for the message, if any.
|
||||
* @throws Exception\InvalidArgumentException For any invalid value.
|
||||
*/
|
||||
private function initialize(
|
||||
$uri = null,
|
||||
?string $method = null,
|
||||
$body = 'php://memory',
|
||||
array $headers = []
|
||||
): void {
|
||||
if ($method !== null) {
|
||||
$this->setMethod($method);
|
||||
}
|
||||
|
||||
$this->uri = $this->createUri($uri);
|
||||
$this->stream = $this->getStream($body, 'wb+');
|
||||
|
||||
$this->setHeaders($headers);
|
||||
|
||||
// per PSR-7: attempt to set the Host header from a provided URI if no
|
||||
// Host header is provided
|
||||
if (! $this->hasHeader('Host') && $this->uri->getHost()) {
|
||||
$this->headerNames['host'] = 'Host';
|
||||
$this->headers['Host'] = [$this->getHostFromUri()];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a URI instance.
|
||||
*
|
||||
* If `$uri` is a already a `UriInterface` instance, returns it.
|
||||
*
|
||||
* If `$uri` is a string, passes it to the `Uri` constructor to return an
|
||||
* instance.
|
||||
*
|
||||
* If `$uri is null, creates and returns an empty `Uri` instance.
|
||||
*
|
||||
* Otherwise, it raises an exception.
|
||||
*
|
||||
* @param null|string|UriInterface $uri
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
private function createUri($uri): UriInterface
|
||||
{
|
||||
if ($uri instanceof UriInterface) {
|
||||
return $uri;
|
||||
}
|
||||
if (is_string($uri)) {
|
||||
return new Uri($uri);
|
||||
}
|
||||
if ($uri === null) {
|
||||
return new Uri();
|
||||
}
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid URI provided; must be null, a string, or a Psr\Http\Message\UriInterface instance'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the message's request target.
|
||||
*
|
||||
* Retrieves the message's request-target either as it will appear (for
|
||||
* clients), as it appeared at request (for servers), or as it was
|
||||
* specified for the instance (see withRequestTarget()).
|
||||
*
|
||||
* In most cases, this will be the origin-form of the composed URI,
|
||||
* unless a value was provided to the concrete implementation (see
|
||||
* withRequestTarget() below).
|
||||
*
|
||||
* If no URI is available, and no request-target has been specifically
|
||||
* provided, this method MUST return the string "/".
|
||||
*/
|
||||
public function getRequestTarget(): string
|
||||
{
|
||||
if (null !== $this->requestTarget) {
|
||||
return $this->requestTarget;
|
||||
}
|
||||
|
||||
$target = $this->uri->getPath();
|
||||
if ($this->uri->getQuery()) {
|
||||
$target .= '?' . $this->uri->getQuery();
|
||||
}
|
||||
|
||||
if (empty($target)) {
|
||||
$target = '/';
|
||||
}
|
||||
|
||||
return $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with a specific request-target.
|
||||
*
|
||||
* If the request needs a non-origin-form request-target — e.g., for
|
||||
* specifying an absolute-form, authority-form, or asterisk-form —
|
||||
* this method may be used to create an instance with the specified
|
||||
* request-target, verbatim.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return a new instance that has the
|
||||
* changed request target.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various
|
||||
* request-target forms allowed in request messages)
|
||||
*
|
||||
* @param string $requestTarget
|
||||
* @throws Exception\InvalidArgumentException If the request target is invalid.
|
||||
* @return static
|
||||
*/
|
||||
public function withRequestTarget($requestTarget): RequestInterface
|
||||
{
|
||||
if (preg_match('#\s#', $requestTarget)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid request target provided; cannot contain whitespace'
|
||||
);
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->requestTarget = $requestTarget;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the HTTP method of the request.
|
||||
*
|
||||
* @return string Returns the request method.
|
||||
*/
|
||||
public function getMethod(): string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the provided HTTP method.
|
||||
*
|
||||
* While HTTP method names are typically all uppercase characters, HTTP
|
||||
* method names are case-sensitive and thus implementations SHOULD NOT
|
||||
* modify the given string.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* changed request method.
|
||||
*
|
||||
* @param string $method Case-insensitive method.
|
||||
* @throws Exception\InvalidArgumentException For invalid HTTP methods.
|
||||
* @return static
|
||||
*/
|
||||
public function withMethod($method): RequestInterface
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->setMethod($method);
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the URI instance.
|
||||
*
|
||||
* This method MUST return a UriInterface instance.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
||||
*
|
||||
* @return UriInterface Returns a UriInterface instance
|
||||
* representing the URI of the request, if any.
|
||||
*/
|
||||
public function getUri(): UriInterface
|
||||
{
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance with the provided URI.
|
||||
*
|
||||
* This method will update the Host header of the returned request by
|
||||
* default if the URI contains a host component. If the URI does not
|
||||
* contain a host component, any pre-existing Host header will be carried
|
||||
* over to the returned request.
|
||||
*
|
||||
* You can opt-in to preserving the original state of the Host header by
|
||||
* setting `$preserveHost` to `true`. When `$preserveHost` is set to
|
||||
* `true`, the returned request will not update the Host header of the
|
||||
* returned message -- even if the message contains no Host header. This
|
||||
* means that a call to `getHeader('Host')` on the original request MUST
|
||||
* equal the return value of a call to `getHeader('Host')` on the returned
|
||||
* request.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new UriInterface instance.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
||||
*
|
||||
* @param UriInterface $uri New request URI to use.
|
||||
* @param bool $preserveHost Preserve the original state of the Host header.
|
||||
* @return static
|
||||
*/
|
||||
public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->uri = $uri;
|
||||
|
||||
if ($preserveHost && $this->hasHeader('Host')) {
|
||||
return $new;
|
||||
}
|
||||
|
||||
if (! $uri->getHost()) {
|
||||
return $new;
|
||||
}
|
||||
|
||||
$host = $uri->getHost();
|
||||
if ($uri->getPort()) {
|
||||
$host .= ':' . $uri->getPort();
|
||||
}
|
||||
|
||||
$new->headerNames['host'] = 'Host';
|
||||
|
||||
// Remove an existing host header if present, regardless of current
|
||||
// de-normalization of the header name.
|
||||
// @see https://github.com/zendframework/zend-diactoros/issues/91
|
||||
foreach (array_keys($new->headers) as $header) {
|
||||
if (strtolower($header) === 'host') {
|
||||
unset($new->headers[$header]);
|
||||
}
|
||||
}
|
||||
|
||||
$new->headers['Host'] = [$host];
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set and validate the HTTP method
|
||||
*
|
||||
* @param string $method
|
||||
* @throws Exception\InvalidArgumentException On invalid HTTP method.
|
||||
*/
|
||||
private function setMethod($method): void
|
||||
{
|
||||
if (! is_string($method)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Unsupported HTTP method; must be a string, received %s',
|
||||
is_object($method) ? $method::class : gettype($method)
|
||||
));
|
||||
}
|
||||
|
||||
if (! preg_match('/^[!#$%&\'*+.^_`\|~0-9a-z-]+$/i', $method)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Unsupported HTTP method "%s" provided',
|
||||
$method
|
||||
));
|
||||
}
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the host from the URI instance
|
||||
*/
|
||||
private function getHostFromUri(): string
|
||||
{
|
||||
$host = $this->uri->getHost();
|
||||
$host .= $this->uri->getPort() ? ':' . $this->uri->getPort() : '';
|
||||
return $host;
|
||||
}
|
||||
}
|
||||
191
libraries/vendor/laminas/laminas-diactoros/src/Response.php
vendored
Normal file
191
libraries/vendor/laminas/laminas-diactoros/src/Response.php
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function gettype;
|
||||
use function is_float;
|
||||
use function is_numeric;
|
||||
use function is_object;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* HTTP response encapsulation.
|
||||
*
|
||||
* Responses are considered immutable; all methods that might change state are
|
||||
* implemented such that they retain the internal state of the current
|
||||
* message and return a new instance that contains the changed state.
|
||||
*/
|
||||
class Response implements ResponseInterface
|
||||
{
|
||||
use MessageTrait;
|
||||
|
||||
public const MIN_STATUS_CODE_VALUE = 100;
|
||||
public const MAX_STATUS_CODE_VALUE = 599;
|
||||
|
||||
/**
|
||||
* Map of standard HTTP status code/reason phrases
|
||||
*
|
||||
* @psalm-var array<positive-int, non-empty-string>
|
||||
*/
|
||||
private array $phrases = [
|
||||
// INFORMATIONAL CODES
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
102 => 'Processing',
|
||||
103 => 'Early Hints',
|
||||
// SUCCESS CODES
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
207 => 'Multi-Status',
|
||||
208 => 'Already Reported',
|
||||
226 => 'IM Used',
|
||||
// REDIRECTION CODES
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
306 => 'Switch Proxy', // Deprecated to 306 => '(Unused)'
|
||||
307 => 'Temporary Redirect',
|
||||
308 => 'Permanent Redirect',
|
||||
// CLIENT ERROR
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Timeout',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Content Too Large',
|
||||
414 => 'URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
418 => 'I\'m a teapot',
|
||||
421 => 'Misdirected Request',
|
||||
422 => 'Unprocessable Content',
|
||||
423 => 'Locked',
|
||||
424 => 'Failed Dependency',
|
||||
425 => 'Too Early',
|
||||
426 => 'Upgrade Required',
|
||||
428 => 'Precondition Required',
|
||||
429 => 'Too Many Requests',
|
||||
431 => 'Request Header Fields Too Large',
|
||||
444 => 'Connection Closed Without Response',
|
||||
451 => 'Unavailable For Legal Reasons',
|
||||
// SERVER ERROR
|
||||
499 => 'Client Closed Request',
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Timeout',
|
||||
505 => 'HTTP Version Not Supported',
|
||||
506 => 'Variant Also Negotiates',
|
||||
507 => 'Insufficient Storage',
|
||||
508 => 'Loop Detected',
|
||||
510 => 'Not Extended (OBSOLETED)',
|
||||
511 => 'Network Authentication Required',
|
||||
599 => 'Network Connect Timeout Error',
|
||||
];
|
||||
|
||||
private string $reasonPhrase;
|
||||
|
||||
private int $statusCode;
|
||||
|
||||
/**
|
||||
* @param string|resource|StreamInterface $body Stream identifier and/or actual stream resource
|
||||
* @param int $status Status code for the response, if any.
|
||||
* @param array $headers Headers for the response, if any.
|
||||
* @throws Exception\InvalidArgumentException On any invalid element.
|
||||
*/
|
||||
public function __construct($body = 'php://memory', int $status = 200, array $headers = [])
|
||||
{
|
||||
$this->setStatusCode($status);
|
||||
$this->stream = $this->getStream($body, 'wb+');
|
||||
$this->setHeaders($headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
return $this->statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getReasonPhrase(): string
|
||||
{
|
||||
return $this->reasonPhrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withStatus($code, $reasonPhrase = ''): Response
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->setStatusCode($code, $reasonPhrase);
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a valid status code.
|
||||
*
|
||||
* @param int $code
|
||||
* @param string $reasonPhrase
|
||||
* @throws Exception\InvalidArgumentException On an invalid status code.
|
||||
*/
|
||||
private function setStatusCode($code, $reasonPhrase = ''): void
|
||||
{
|
||||
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 "%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
|
||||
));
|
||||
}
|
||||
|
||||
if (! is_string($reasonPhrase)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Unsupported response reason phrase; must be a string, received %s',
|
||||
is_object($reasonPhrase) ? $reasonPhrase::class : gettype($reasonPhrase)
|
||||
));
|
||||
}
|
||||
|
||||
if ($reasonPhrase === '' && isset($this->phrases[$code])) {
|
||||
$reasonPhrase = $this->phrases[$code];
|
||||
}
|
||||
|
||||
$this->reasonPhrase = $reasonPhrase;
|
||||
$this->statusCode = (int) $code;
|
||||
}
|
||||
}
|
||||
84
libraries/vendor/laminas/laminas-diactoros/src/Response/ArraySerializer.php
vendored
Normal file
84
libraries/vendor/laminas/laminas-diactoros/src/Response/ArraySerializer.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Serialize or deserialize response messages to/from arrays.
|
||||
*
|
||||
* This class provides functionality for serializing a ResponseInterface instance
|
||||
* to an array, as well as the reverse operation of creating a Response instance
|
||||
* from an array representing a message.
|
||||
*/
|
||||
final class ArraySerializer
|
||||
{
|
||||
/**
|
||||
* Serialize a response message to an array.
|
||||
*
|
||||
* @return array{
|
||||
* status_code: int,
|
||||
* reason_phrase: string,
|
||||
* protocol_version: string,
|
||||
* headers: array<array<string>>,
|
||||
* body: string
|
||||
* }
|
||||
*/
|
||||
public static function toArray(ResponseInterface $response): array
|
||||
{
|
||||
return [
|
||||
'status_code' => $response->getStatusCode(),
|
||||
'reason_phrase' => $response->getReasonPhrase(),
|
||||
'protocol_version' => $response->getProtocolVersion(),
|
||||
'headers' => $response->getHeaders(),
|
||||
'body' => (string) $response->getBody(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a response array to a response instance.
|
||||
*
|
||||
* @throws Exception\DeserializationException When cannot deserialize response.
|
||||
*/
|
||||
public static function fromArray(array $serializedResponse): Response
|
||||
{
|
||||
try {
|
||||
$body = new Stream('php://memory', 'wb+');
|
||||
$body->write(self::getValueFromKey($serializedResponse, 'body'));
|
||||
|
||||
$statusCode = self::getValueFromKey($serializedResponse, 'status_code');
|
||||
$headers = self::getValueFromKey($serializedResponse, 'headers');
|
||||
$protocolVersion = self::getValueFromKey($serializedResponse, 'protocol_version');
|
||||
$reasonPhrase = self::getValueFromKey($serializedResponse, 'reason_phrase');
|
||||
|
||||
return (new Response($body, $statusCode, $headers))
|
||||
->withProtocolVersion($protocolVersion)
|
||||
->withStatus($statusCode, $reasonPhrase);
|
||||
} catch (Throwable $exception) {
|
||||
throw Exception\DeserializationException::forResponseFromArray($exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception\DeserializationException
|
||||
*/
|
||||
private static function getValueFromKey(array $data, string $key, ?string $message = null)
|
||||
{
|
||||
if (isset($data[$key])) {
|
||||
return $data[$key];
|
||||
}
|
||||
if ($message === null) {
|
||||
$message = sprintf('Missing "%s" key in serialized response', $key);
|
||||
}
|
||||
throw new Exception\DeserializationException($message);
|
||||
}
|
||||
}
|
||||
36
libraries/vendor/laminas/laminas-diactoros/src/Response/EmptyResponse.php
vendored
Normal file
36
libraries/vendor/laminas/laminas-diactoros/src/Response/EmptyResponse.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\Stream;
|
||||
|
||||
/**
|
||||
* A class representing empty HTTP responses.
|
||||
*/
|
||||
class EmptyResponse extends Response
|
||||
{
|
||||
/**
|
||||
* Create an empty response with the given status code.
|
||||
*
|
||||
* @param int $status Status code for the response, if any.
|
||||
* @param array $headers Headers for the response, if any.
|
||||
*/
|
||||
public function __construct(int $status = 204, array $headers = [])
|
||||
{
|
||||
$body = new Stream('php://temp', 'r');
|
||||
parent::__construct($body, $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty response with the given headers.
|
||||
*
|
||||
* @param array $headers Headers for the response.
|
||||
*/
|
||||
public static function withHeaders(array $headers): EmptyResponse
|
||||
{
|
||||
return new static(204, $headers);
|
||||
}
|
||||
}
|
||||
73
libraries/vendor/laminas/laminas-diactoros/src/Response/HtmlResponse.php
vendored
Normal file
73
libraries/vendor/laminas/laminas-diactoros/src/Response/HtmlResponse.php
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* HTML response.
|
||||
*
|
||||
* Allows creating a response by passing an HTML string to the constructor;
|
||||
* by default, sets a status code of 200 and sets the Content-Type header to
|
||||
* text/html.
|
||||
*/
|
||||
class HtmlResponse extends Response
|
||||
{
|
||||
use InjectContentTypeTrait;
|
||||
|
||||
/**
|
||||
* Create an HTML response.
|
||||
*
|
||||
* Produces an HTML response with a Content-Type of text/html and a default
|
||||
* status of 200.
|
||||
*
|
||||
* @param string|StreamInterface $html HTML or stream for the message body.
|
||||
* @param int $status Integer status code for the response; 200 by default.
|
||||
* @param array $headers Array of headers to use at initialization.
|
||||
* @throws Exception\InvalidArgumentException If $html is neither a string or stream.
|
||||
*/
|
||||
public function __construct($html, int $status = 200, array $headers = [])
|
||||
{
|
||||
parent::__construct(
|
||||
$this->createBody($html),
|
||||
$status,
|
||||
$this->injectContentType('text/html; charset=utf-8', $headers)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the message body.
|
||||
*
|
||||
* @param string|StreamInterface $html
|
||||
* @throws Exception\InvalidArgumentException If $html is neither a string or stream.
|
||||
*/
|
||||
private function createBody($html): StreamInterface
|
||||
{
|
||||
if ($html instanceof StreamInterface) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
if (! is_string($html)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Invalid content (%s) provided to %s',
|
||||
is_object($html) ? $html::class : gettype($html),
|
||||
self::class
|
||||
));
|
||||
}
|
||||
|
||||
$body = new Stream('php://temp', 'wb+');
|
||||
$body->write($html);
|
||||
$body->rewind();
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
32
libraries/vendor/laminas/laminas-diactoros/src/Response/InjectContentTypeTrait.php
vendored
Normal file
32
libraries/vendor/laminas/laminas-diactoros/src/Response/InjectContentTypeTrait.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use function array_keys;
|
||||
use function array_reduce;
|
||||
use function strtolower;
|
||||
|
||||
trait InjectContentTypeTrait
|
||||
{
|
||||
/**
|
||||
* Inject the provided Content-Type, if none is already present.
|
||||
*
|
||||
* @return array Headers with injected Content-Type
|
||||
*/
|
||||
private function injectContentType(string $contentType, array $headers): array
|
||||
{
|
||||
$hasContentType = array_reduce(
|
||||
array_keys($headers),
|
||||
static fn($carry, $item) => $carry ?: strtolower($item) === 'content-type',
|
||||
false
|
||||
);
|
||||
|
||||
if (! $hasContentType) {
|
||||
$headers['content-type'] = [$contentType];
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
}
|
||||
168
libraries/vendor/laminas/laminas-diactoros/src/Response/JsonResponse.php
vendored
Normal file
168
libraries/vendor/laminas/laminas-diactoros/src/Response/JsonResponse.php
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\Stream;
|
||||
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function json_encode;
|
||||
use function json_last_error;
|
||||
use function json_last_error_msg;
|
||||
use function sprintf;
|
||||
|
||||
use const JSON_ERROR_NONE;
|
||||
use const JSON_HEX_AMP;
|
||||
use const JSON_HEX_APOS;
|
||||
use const JSON_HEX_QUOT;
|
||||
use const JSON_HEX_TAG;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
|
||||
/**
|
||||
* JSON response.
|
||||
*
|
||||
* Allows creating a response by passing data to the constructor; by default,
|
||||
* serializes the data to JSON, sets a status code of 200 and sets the
|
||||
* Content-Type header to application/json.
|
||||
*/
|
||||
class JsonResponse extends Response
|
||||
{
|
||||
use InjectContentTypeTrait;
|
||||
|
||||
/**
|
||||
* Default flags for json_encode
|
||||
*
|
||||
* @const int
|
||||
*/
|
||||
public const DEFAULT_JSON_FLAGS = JSON_HEX_TAG
|
||||
| JSON_HEX_APOS
|
||||
| JSON_HEX_AMP
|
||||
| JSON_HEX_QUOT
|
||||
| JSON_UNESCAPED_SLASHES;
|
||||
|
||||
/** @var mixed */
|
||||
private $payload;
|
||||
|
||||
/**
|
||||
* Create a JSON response with the given data.
|
||||
*
|
||||
* Default JSON encoding is performed with the following options, which
|
||||
* produces RFC4627-compliant JSON, capable of embedding into HTML.
|
||||
*
|
||||
* - JSON_HEX_TAG
|
||||
* - JSON_HEX_APOS
|
||||
* - JSON_HEX_AMP
|
||||
* - JSON_HEX_QUOT
|
||||
* - JSON_UNESCAPED_SLASHES
|
||||
*
|
||||
* @param mixed $data Data to convert to JSON.
|
||||
* @param int $status Integer status code for the response; 200 by default.
|
||||
* @param array $headers Array of headers to use at initialization.
|
||||
* @param int $encodingOptions JSON encoding options to use.
|
||||
* @throws Exception\InvalidArgumentException If unable to encode the $data to JSON.
|
||||
*/
|
||||
public function __construct(
|
||||
$data,
|
||||
int $status = 200,
|
||||
array $headers = [],
|
||||
private int $encodingOptions = self::DEFAULT_JSON_FLAGS
|
||||
) {
|
||||
$this->setPayload($data);
|
||||
|
||||
$json = $this->jsonEncode($data, $this->encodingOptions);
|
||||
$body = $this->createBodyFromJson($json);
|
||||
|
||||
$headers = $this->injectContentType('application/json', $headers);
|
||||
|
||||
parent::__construct($body, $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPayload()
|
||||
{
|
||||
return $this->payload;
|
||||
}
|
||||
|
||||
public function withPayload(mixed $data): JsonResponse
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->setPayload($data);
|
||||
return $this->updateBodyFor($new);
|
||||
}
|
||||
|
||||
public function getEncodingOptions(): int
|
||||
{
|
||||
return $this->encodingOptions;
|
||||
}
|
||||
|
||||
public function withEncodingOptions(int $encodingOptions): JsonResponse
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->encodingOptions = $encodingOptions;
|
||||
return $this->updateBodyFor($new);
|
||||
}
|
||||
|
||||
private function createBodyFromJson(string $json): Stream
|
||||
{
|
||||
$body = new Stream('php://temp', 'wb+');
|
||||
$body->write($json);
|
||||
$body->rewind();
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the provided data to JSON.
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException If unable to encode the $data to JSON.
|
||||
*/
|
||||
private function jsonEncode(mixed $data, int $encodingOptions): string
|
||||
{
|
||||
if (is_resource($data)) {
|
||||
throw new Exception\InvalidArgumentException('Cannot JSON encode resources');
|
||||
}
|
||||
|
||||
// Clear json_last_error()
|
||||
json_encode(null);
|
||||
|
||||
$json = json_encode($data, $encodingOptions);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Unable to encode data to JSON in %s: %s',
|
||||
self::class,
|
||||
json_last_error_msg()
|
||||
));
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
private function setPayload(mixed $data): void
|
||||
{
|
||||
if (is_object($data)) {
|
||||
$data = clone $data;
|
||||
}
|
||||
|
||||
$this->payload = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the response body for the given instance.
|
||||
*
|
||||
* @param self $toUpdate Instance to update.
|
||||
* @return JsonResponse Returns a new instance with an updated body.
|
||||
*/
|
||||
private function updateBodyFor(JsonResponse $toUpdate): JsonResponse
|
||||
{
|
||||
$json = $this->jsonEncode($toUpdate->payload, $toUpdate->encodingOptions);
|
||||
$body = $this->createBodyFromJson($json);
|
||||
return $toUpdate->withBody($body);
|
||||
}
|
||||
}
|
||||
46
libraries/vendor/laminas/laminas-diactoros/src/Response/RedirectResponse.php
vendored
Normal file
46
libraries/vendor/laminas/laminas-diactoros/src/Response/RedirectResponse.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Produce a redirect response.
|
||||
*/
|
||||
class RedirectResponse extends Response
|
||||
{
|
||||
/**
|
||||
* Create a redirect response.
|
||||
*
|
||||
* Produces a redirect response with a Location header and the given status
|
||||
* (302 by default).
|
||||
*
|
||||
* Note: this method overwrites the `location` $headers value.
|
||||
*
|
||||
* @param string|UriInterface $uri URI for the Location header.
|
||||
* @param int $status Integer status code for the redirect; 302 by default.
|
||||
* @param array $headers Array of headers to use at initialization.
|
||||
*/
|
||||
public function __construct($uri, int $status = 302, array $headers = [])
|
||||
{
|
||||
if (! is_string($uri) && ! $uri instanceof UriInterface) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Uri provided to %s MUST be a string or Psr\Http\Message\UriInterface instance; received "%s"',
|
||||
self::class,
|
||||
is_object($uri) ? $uri::class : gettype($uri)
|
||||
));
|
||||
}
|
||||
|
||||
$headers['location'] = [(string) $uri];
|
||||
parent::__construct('php://temp', $status, $headers);
|
||||
}
|
||||
}
|
||||
101
libraries/vendor/laminas/laminas-diactoros/src/Response/Serializer.php
vendored
Normal file
101
libraries/vendor/laminas/laminas-diactoros/src/Response/Serializer.php
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\AbstractSerializer;
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
|
||||
final class Serializer extends AbstractSerializer
|
||||
{
|
||||
/**
|
||||
* Deserialize a response string to a response instance.
|
||||
*
|
||||
* @throws Exception\SerializationException When errors occur parsing the message.
|
||||
*/
|
||||
public static function fromString(string $message): Response
|
||||
{
|
||||
$stream = new Stream('php://temp', 'wb+');
|
||||
$stream->write($message);
|
||||
return static::fromStream($stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a response from a stream.
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException When the stream is not readable.
|
||||
* @throws Exception\SerializationException When errors occur parsing the message.
|
||||
*/
|
||||
public static function fromStream(StreamInterface $stream): Response
|
||||
{
|
||||
if (! $stream->isReadable() || ! $stream->isSeekable()) {
|
||||
throw new Exception\InvalidArgumentException('Message stream must be both readable and seekable');
|
||||
}
|
||||
|
||||
$stream->rewind();
|
||||
|
||||
[$version, $status, $reasonPhrase] = self::getStatusLine($stream);
|
||||
[$headers, $body] = self::splitStream($stream);
|
||||
|
||||
return (new Response($body, $status, $headers))
|
||||
->withProtocolVersion($version)
|
||||
->withStatus((int) $status, $reasonPhrase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string representation of a response.
|
||||
*/
|
||||
public static function toString(ResponseInterface $response): string
|
||||
{
|
||||
$reasonPhrase = $response->getReasonPhrase();
|
||||
$headers = self::serializeHeaders($response->getHeaders());
|
||||
$body = (string) $response->getBody();
|
||||
$format = 'HTTP/%s %d%s%s%s';
|
||||
|
||||
if (! empty($headers)) {
|
||||
$headers = "\r\n" . $headers;
|
||||
}
|
||||
|
||||
$headers .= "\r\n\r\n";
|
||||
|
||||
return sprintf(
|
||||
$format,
|
||||
$response->getProtocolVersion(),
|
||||
$response->getStatusCode(),
|
||||
$reasonPhrase ? ' ' . $reasonPhrase : '',
|
||||
$headers,
|
||||
$body
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the status line for the message.
|
||||
*
|
||||
* @return array Array with three elements: 0 => version, 1 => status, 2 => reason
|
||||
* @throws Exception\SerializationException If line is malformed.
|
||||
*/
|
||||
private static function getStatusLine(StreamInterface $stream): array
|
||||
{
|
||||
$line = self::getLine($stream);
|
||||
|
||||
if (
|
||||
! preg_match(
|
||||
'#^HTTP/(?P<version>[1-9]\d*\.\d) (?P<status>[1-5]\d{2})(\s+(?P<reason>.+))?$#',
|
||||
$line,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
throw Exception\SerializationException::forInvalidStatusLine();
|
||||
}
|
||||
|
||||
return [$matches['version'], (int) $matches['status'], $matches['reason'] ?? ''];
|
||||
}
|
||||
}
|
||||
73
libraries/vendor/laminas/laminas-diactoros/src/Response/TextResponse.php
vendored
Normal file
73
libraries/vendor/laminas/laminas-diactoros/src/Response/TextResponse.php
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Plain text response.
|
||||
*
|
||||
* Allows creating a response by passing a string to the constructor;
|
||||
* by default, sets a status code of 200 and sets the Content-Type header to
|
||||
* text/plain.
|
||||
*/
|
||||
class TextResponse extends Response
|
||||
{
|
||||
use InjectContentTypeTrait;
|
||||
|
||||
/**
|
||||
* Create a plain text response.
|
||||
*
|
||||
* Produces a text response with a Content-Type of text/plain and a default
|
||||
* status of 200.
|
||||
*
|
||||
* @param string|StreamInterface $text String or stream for the message body.
|
||||
* @param int $status Integer status code for the response; 200 by default.
|
||||
* @param array $headers Array of headers to use at initialization.
|
||||
* @throws Exception\InvalidArgumentException If $text is neither a string or stream.
|
||||
*/
|
||||
public function __construct($text, int $status = 200, array $headers = [])
|
||||
{
|
||||
parent::__construct(
|
||||
$this->createBody($text),
|
||||
$status,
|
||||
$this->injectContentType('text/plain; charset=utf-8', $headers)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the message body.
|
||||
*
|
||||
* @param string|StreamInterface $text
|
||||
* @throws Exception\InvalidArgumentException If $text is neither a string or stream.
|
||||
*/
|
||||
private function createBody($text): StreamInterface
|
||||
{
|
||||
if ($text instanceof StreamInterface) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (! is_string($text)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Invalid content (%s) provided to %s',
|
||||
is_object($text) ? $text::class : gettype($text),
|
||||
self::class
|
||||
));
|
||||
}
|
||||
|
||||
$body = new Stream('php://temp', 'wb+');
|
||||
$body->write($text);
|
||||
$body->rewind();
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
75
libraries/vendor/laminas/laminas-diactoros/src/Response/XmlResponse.php
vendored
Normal file
75
libraries/vendor/laminas/laminas-diactoros/src/Response/XmlResponse.php
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\Response;
|
||||
|
||||
use Laminas\Diactoros\Exception;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* XML response.
|
||||
*
|
||||
* Allows creating a response by passing an XML string to the constructor; by default,
|
||||
* sets a status code of 200 and sets the Content-Type header to application/xml.
|
||||
*/
|
||||
class XmlResponse extends Response
|
||||
{
|
||||
use InjectContentTypeTrait;
|
||||
|
||||
/**
|
||||
* Create an XML response.
|
||||
*
|
||||
* Produces an XML response with a Content-Type of application/xml and a default
|
||||
* status of 200.
|
||||
*
|
||||
* @param string|StreamInterface $xml String or stream for the message body.
|
||||
* @param int $status Integer status code for the response; 200 by default.
|
||||
* @param array $headers Array of headers to use at initialization.
|
||||
* @throws Exception\InvalidArgumentException If $text is neither a string or stream.
|
||||
*/
|
||||
public function __construct(
|
||||
$xml,
|
||||
int $status = 200,
|
||||
array $headers = []
|
||||
) {
|
||||
parent::__construct(
|
||||
$this->createBody($xml),
|
||||
$status,
|
||||
$this->injectContentType('application/xml; charset=utf-8', $headers)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the message body.
|
||||
*
|
||||
* @param string|StreamInterface $xml
|
||||
* @throws Exception\InvalidArgumentException If $xml is neither a string or stream.
|
||||
*/
|
||||
private function createBody($xml): StreamInterface
|
||||
{
|
||||
if ($xml instanceof StreamInterface) {
|
||||
return $xml;
|
||||
}
|
||||
|
||||
if (! is_string($xml)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Invalid content (%s) provided to %s',
|
||||
is_object($xml) ? $xml::class : gettype($xml),
|
||||
self::class
|
||||
));
|
||||
}
|
||||
|
||||
$body = new Stream('php://temp', 'wb+');
|
||||
$body->write($xml);
|
||||
$body->rewind();
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
20
libraries/vendor/laminas/laminas-diactoros/src/ResponseFactory.php
vendored
Normal file
20
libraries/vendor/laminas/laminas-diactoros/src/ResponseFactory.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\ResponseFactoryInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class ResponseFactory implements ResponseFactoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
|
||||
{
|
||||
return (new Response())
|
||||
->withStatus($code, $reasonPhrase);
|
||||
}
|
||||
}
|
||||
223
libraries/vendor/laminas/laminas-diactoros/src/ServerRequest.php
vendored
Normal file
223
libraries/vendor/laminas/laminas-diactoros/src/ServerRequest.php
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function gettype;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Server-side HTTP request
|
||||
*
|
||||
* Extends the Request definition to add methods for accessing incoming data,
|
||||
* specifically server parameters, cookies, matched path parameters, query
|
||||
* string arguments, body parameters, and upload file information.
|
||||
*
|
||||
* "Attributes" are discovered via decomposing the request (and usually
|
||||
* specifically the URI path), and typically will be injected by the application.
|
||||
*
|
||||
* Requests are considered immutable; all methods that might change state are
|
||||
* implemented such that they retain the internal state of the current
|
||||
* message and return a new instance that contains the changed state.
|
||||
*/
|
||||
class ServerRequest implements ServerRequestInterface
|
||||
{
|
||||
use RequestTrait;
|
||||
|
||||
private array $attributes = [];
|
||||
|
||||
private array $uploadedFiles;
|
||||
|
||||
/**
|
||||
* @param array $serverParams Server parameters, typically from $_SERVER
|
||||
* @param array $uploadedFiles Upload file information, a tree of UploadedFiles
|
||||
* @param null|string|UriInterface $uri URI for the request, if any.
|
||||
* @param null|string $method HTTP method for the request, if any.
|
||||
* @param string|resource|StreamInterface $body Message body, if any.
|
||||
* @param array $headers Headers for the message, if any.
|
||||
* @param array $cookieParams Cookies for the message, if any.
|
||||
* @param array $queryParams Query params for the message, if any.
|
||||
* @param null|array|object $parsedBody The deserialized body parameters, if any.
|
||||
* @param string $protocol HTTP protocol version.
|
||||
* @throws Exception\InvalidArgumentException For any invalid value.
|
||||
*/
|
||||
public function __construct(
|
||||
private array $serverParams = [],
|
||||
array $uploadedFiles = [],
|
||||
$uri = null,
|
||||
?string $method = null,
|
||||
$body = 'php://input',
|
||||
array $headers = [],
|
||||
private array $cookieParams = [],
|
||||
private array $queryParams = [],
|
||||
private $parsedBody = null,
|
||||
string $protocol = '1.1'
|
||||
) {
|
||||
$this->validateUploadedFiles($uploadedFiles);
|
||||
|
||||
if ($body === 'php://input') {
|
||||
$body = new PhpInputStream();
|
||||
}
|
||||
|
||||
$this->initialize($uri, $method, $body, $headers);
|
||||
$this->uploadedFiles = $uploadedFiles;
|
||||
$this->protocol = $protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getServerParams(): array
|
||||
{
|
||||
return $this->serverParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getUploadedFiles(): array
|
||||
{
|
||||
return $this->uploadedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withUploadedFiles(array $uploadedFiles): ServerRequest
|
||||
{
|
||||
$this->validateUploadedFiles($uploadedFiles);
|
||||
$new = clone $this;
|
||||
$new->uploadedFiles = $uploadedFiles;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCookieParams(): array
|
||||
{
|
||||
return $this->cookieParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withCookieParams(array $cookies): ServerRequest
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->cookieParams = $cookies;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQueryParams(): array
|
||||
{
|
||||
return $this->queryParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withQueryParams(array $query): ServerRequest
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->queryParams = $query;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParsedBody()
|
||||
{
|
||||
return $this->parsedBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withParsedBody($data): ServerRequest
|
||||
{
|
||||
if (! is_array($data) && ! is_object($data) && null !== $data) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a null, array, or object argument; received %s',
|
||||
__METHOD__,
|
||||
gettype($data)
|
||||
));
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->parsedBody = $data;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAttribute($attribute, $default = null)
|
||||
{
|
||||
if (! array_key_exists($attribute, $this->attributes)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->attributes[$attribute];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withAttribute($attribute, $value): ServerRequest
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->attributes[$attribute] = $value;
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withoutAttribute($name): ServerRequest
|
||||
{
|
||||
$new = clone $this;
|
||||
unset($new->attributes[$name]);
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively validate the structure in an uploaded files array.
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException If any leaf is not an UploadedFileInterface instance.
|
||||
*/
|
||||
private function validateUploadedFiles(array $uploadedFiles): void
|
||||
{
|
||||
foreach ($uploadedFiles as $file) {
|
||||
if (is_array($file)) {
|
||||
$this->validateUploadedFiles($file);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $file instanceof UploadedFileInterface) {
|
||||
throw new Exception\InvalidArgumentException('Invalid leaf in uploaded files structure');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
99
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFactory.php
vendored
Normal file
99
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFactory.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Laminas\Diactoros\ServerRequestFilter\FilterServerRequestInterface;
|
||||
use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders;
|
||||
use Psr\Http\Message\ServerRequestFactoryInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function is_callable;
|
||||
|
||||
/**
|
||||
* Class for marshaling a request object from the current PHP environment.
|
||||
*/
|
||||
class ServerRequestFactory implements ServerRequestFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Function to use to get apache request headers; present only to simplify mocking.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
private static $apacheRequestHeaders = 'apache_request_headers';
|
||||
|
||||
/**
|
||||
* Create a request from the supplied superglobal values.
|
||||
*
|
||||
* If any argument is not supplied, the corresponding superglobal value will
|
||||
* be used.
|
||||
*
|
||||
* The ServerRequest created is then passed to the fromServer() method in
|
||||
* order to marshal the request URI and headers.
|
||||
*
|
||||
* @see fromServer()
|
||||
*
|
||||
* @param array $server $_SERVER superglobal
|
||||
* @param array $query $_GET superglobal
|
||||
* @param array $body $_POST superglobal
|
||||
* @param array $cookies $_COOKIE superglobal
|
||||
* @param array $files $_FILES superglobal
|
||||
* @param null|FilterServerRequestInterface $requestFilter If present, the
|
||||
* generated request will be passed to this instance and the result
|
||||
* returned by this method. When not present, a default instance of
|
||||
* FilterUsingXForwardedHeaders is created, using the `trustReservedSubnets()`
|
||||
* constructor.
|
||||
*/
|
||||
public static function fromGlobals(
|
||||
?array $server = null,
|
||||
?array $query = null,
|
||||
?array $body = null,
|
||||
?array $cookies = null,
|
||||
?array $files = null,
|
||||
?FilterServerRequestInterface $requestFilter = null
|
||||
): ServerRequest {
|
||||
$requestFilter = $requestFilter ?: FilterUsingXForwardedHeaders::trustReservedSubnets();
|
||||
|
||||
$server = normalizeServer(
|
||||
$server ?: $_SERVER,
|
||||
is_callable(self::$apacheRequestHeaders) ? self::$apacheRequestHeaders : null
|
||||
);
|
||||
$files = normalizeUploadedFiles($files ?: $_FILES);
|
||||
$headers = marshalHeadersFromSapi($server);
|
||||
|
||||
if (null === $cookies && array_key_exists('cookie', $headers)) {
|
||||
$cookies = parseCookieHeader($headers['cookie']);
|
||||
}
|
||||
|
||||
return $requestFilter(new ServerRequest(
|
||||
$server,
|
||||
$files,
|
||||
UriFactory::createFromSapi($server, $headers),
|
||||
marshalMethodFromSapi($server),
|
||||
'php://input',
|
||||
$headers,
|
||||
$cookies ?: $_COOKIE,
|
||||
$query ?: $_GET,
|
||||
$body ?: $_POST,
|
||||
marshalProtocolVersionFromSapi($server)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
|
||||
{
|
||||
$uploadedFiles = [];
|
||||
|
||||
return new ServerRequest(
|
||||
$serverParams,
|
||||
$uploadedFiles,
|
||||
$uri,
|
||||
$method,
|
||||
'php://temp'
|
||||
);
|
||||
}
|
||||
}
|
||||
15
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/DoNotFilter.php
vendored
Normal file
15
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/DoNotFilter.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\ServerRequestFilter;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
final class DoNotFilter implements FilterServerRequestInterface
|
||||
{
|
||||
public function __invoke(ServerRequestInterface $request): ServerRequestInterface
|
||||
{
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\ServerRequestFilter;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Filter/initialize a server request.
|
||||
*
|
||||
* Implementations of this interface will take an incoming request, and
|
||||
* decide if additional modifications are necessary. As examples:
|
||||
*
|
||||
* - Injecting a unique request identifier header.
|
||||
* - Using the X-Forwarded-* headers to rewrite the URI to reflect the original request.
|
||||
* - Using the Forwarded header to rewrite the URI to reflect the original request.
|
||||
*
|
||||
* This functionality is consumed by the ServerRequestFactory using the request
|
||||
* instance it generates, just prior to returning a request.
|
||||
*/
|
||||
interface FilterServerRequestInterface
|
||||
{
|
||||
/**
|
||||
* Determine if a request needs further modification, and if so, return a
|
||||
* new instance reflecting those modifications.
|
||||
*/
|
||||
public function __invoke(ServerRequestInterface $request): ServerRequestInterface;
|
||||
}
|
||||
263
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php
vendored
Normal file
263
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php
vendored
Normal file
@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\ServerRequestFilter;
|
||||
|
||||
use Laminas\Diactoros\Exception\InvalidForwardedHeaderNameException;
|
||||
use Laminas\Diactoros\Exception\InvalidProxyAddressException;
|
||||
use Laminas\Diactoros\UriFactory;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
use function assert;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function filter_var;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
use function str_contains;
|
||||
use function strtolower;
|
||||
|
||||
use const FILTER_FLAG_IPV4;
|
||||
use const FILTER_FLAG_IPV6;
|
||||
use const FILTER_VALIDATE_IP;
|
||||
|
||||
/**
|
||||
* Modify the URI to reflect the X-Forwarded-* headers.
|
||||
*
|
||||
* If the request comes from a trusted proxy, this filter will analyze the
|
||||
* various X-Forwarded-* headers, if any, and if they are marked as trusted,
|
||||
* in order to return a new request that composes a URI instance that reflects
|
||||
* those headers.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class FilterUsingXForwardedHeaders implements FilterServerRequestInterface
|
||||
{
|
||||
public const HEADER_HOST = 'X-FORWARDED-HOST';
|
||||
public const HEADER_PORT = 'X-FORWARDED-PORT';
|
||||
public const HEADER_PROTO = 'X-FORWARDED-PROTO';
|
||||
|
||||
private const X_FORWARDED_HEADERS = [
|
||||
self::HEADER_HOST,
|
||||
self::HEADER_PORT,
|
||||
self::HEADER_PROTO,
|
||||
];
|
||||
|
||||
/**
|
||||
* Only allow construction via named constructors
|
||||
*
|
||||
* @param list<non-empty-string> $trustedProxies
|
||||
* @param list<FilterUsingXForwardedHeaders::HEADER_*> $trustedHeaders
|
||||
*/
|
||||
private function __construct(private array $trustedProxies = [], private array $trustedHeaders = [])
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request): ServerRequestInterface
|
||||
{
|
||||
$remoteAddress = $request->getServerParams()['REMOTE_ADDR'] ?? '';
|
||||
|
||||
if ('' === $remoteAddress || ! is_string($remoteAddress)) {
|
||||
// Should we trigger a warning here?
|
||||
return $request;
|
||||
}
|
||||
|
||||
if (! $this->isFromTrustedProxy($remoteAddress)) {
|
||||
// Do nothing
|
||||
return $request;
|
||||
}
|
||||
|
||||
// Update the URI based on the trusted headers
|
||||
$uri = $originalUri = $request->getUri();
|
||||
foreach ($this->trustedHeaders as $headerName) {
|
||||
$header = $request->getHeaderLine($headerName);
|
||||
if ('' === $header || str_contains($header, ',')) {
|
||||
// Reject empty headers and/or headers with multiple values
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($headerName) {
|
||||
case self::HEADER_HOST:
|
||||
[$host, $port] = UriFactory::marshalHostAndPortFromHeader($header);
|
||||
$uri = $uri
|
||||
->withHost($host);
|
||||
if ($port !== null) {
|
||||
$uri = $uri->withPort($port);
|
||||
}
|
||||
break;
|
||||
case self::HEADER_PORT:
|
||||
$uri = $uri->withPort((int) $header);
|
||||
break;
|
||||
case self::HEADER_PROTO:
|
||||
$scheme = strtolower($header) === 'https' ? 'https' : 'http';
|
||||
$uri = $uri->withScheme($scheme);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($uri !== $originalUri) {
|
||||
return $request->withUri($uri);
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate which proxies and which X-Forwarded headers to trust.
|
||||
*
|
||||
* @param list<non-empty-string> $proxyCIDRList Each element may
|
||||
* be an IP address or a subnet specified using CIDR notation; both IPv4
|
||||
* and IPv6 are supported. The special string "*" will be translated to
|
||||
* two entries, "0.0.0.0/0" and "::/0". An empty list indicates no
|
||||
* proxies are trusted.
|
||||
* @param list<FilterUsingXForwardedHeaders::HEADER_*> $trustedHeaders If
|
||||
* the list is empty, all X-Forwarded headers are trusted.
|
||||
* @throws InvalidProxyAddressException
|
||||
* @throws InvalidForwardedHeaderNameException
|
||||
*/
|
||||
public static function trustProxies(
|
||||
array $proxyCIDRList,
|
||||
array $trustedHeaders = self::X_FORWARDED_HEADERS
|
||||
): self {
|
||||
$proxyCIDRList = self::normalizeProxiesList($proxyCIDRList);
|
||||
self::validateTrustedHeaders($trustedHeaders);
|
||||
|
||||
return new self($proxyCIDRList, $trustedHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trust any X-FORWARDED-* headers from any address.
|
||||
*
|
||||
* This is functionally equivalent to calling `trustProxies(['*'])`.
|
||||
*
|
||||
* WARNING: Only do this if you know for certain that your application
|
||||
* sits behind a trusted proxy that cannot be spoofed. This should only
|
||||
* be the case if your server is not publicly addressable, and all requests
|
||||
* are routed via a reverse proxy (e.g., a load balancer, a server such as
|
||||
* Caddy, when using Traefik, etc.).
|
||||
*/
|
||||
public static function trustAny(): self
|
||||
{
|
||||
return self::trustProxies(['*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trust X-Forwarded headers from reserved subnetworks.
|
||||
*
|
||||
* This is functionally equivalent to calling `trustProxies()` where the
|
||||
* `$proxcyCIDRList` argument is a list with the following:
|
||||
*
|
||||
* - 10.0.0.0/8
|
||||
* - 127.0.0.0/8
|
||||
* - 172.16.0.0/12
|
||||
* - 192.168.0.0/16
|
||||
* - ::1/128 (IPv6 localhost)
|
||||
* - fc00::/7 (IPv6 private networks)
|
||||
* - fe80::/10 (IPv6 local-link addresses)
|
||||
*
|
||||
* @param list<FilterUsingXForwardedHeaders::HEADER_*> $trustedHeaders If
|
||||
* the list is empty, all X-Forwarded headers are trusted.
|
||||
* @throws InvalidForwardedHeaderNameException
|
||||
*/
|
||||
public static function trustReservedSubnets(array $trustedHeaders = self::X_FORWARDED_HEADERS): self
|
||||
{
|
||||
return self::trustProxies([
|
||||
'10.0.0.0/8',
|
||||
'127.0.0.0/8',
|
||||
'172.16.0.0/12',
|
||||
'192.168.0.0/16',
|
||||
'::1/128', // ipv6 localhost
|
||||
'fc00::/7', // ipv6 private networks
|
||||
'fe80::/10', // ipv6 local-link addresses
|
||||
], $trustedHeaders);
|
||||
}
|
||||
|
||||
private function isFromTrustedProxy(string $remoteAddress): bool
|
||||
{
|
||||
foreach ($this->trustedProxies as $proxy) {
|
||||
if (IPRange::matches($remoteAddress, $proxy)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @throws InvalidForwardedHeaderNameException */
|
||||
private static function validateTrustedHeaders(array $headers): void
|
||||
{
|
||||
foreach ($headers as $header) {
|
||||
if (! in_array($header, self::X_FORWARDED_HEADERS, true)) {
|
||||
throw InvalidForwardedHeaderNameException::forHeader($header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<non-empty-string> $proxyCIDRList
|
||||
* @return list<non-empty-string>
|
||||
* @throws InvalidProxyAddressException
|
||||
*/
|
||||
private static function normalizeProxiesList(array $proxyCIDRList): array
|
||||
{
|
||||
$foundWildcard = false;
|
||||
|
||||
foreach ($proxyCIDRList as $index => $cidr) {
|
||||
if ($cidr === '*') {
|
||||
unset($proxyCIDRList[$index]);
|
||||
$foundWildcard = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! self::validateProxyCIDR($cidr)) {
|
||||
throw InvalidProxyAddressException::forAddress($cidr);
|
||||
}
|
||||
}
|
||||
|
||||
if ($foundWildcard) {
|
||||
$proxyCIDRList[] = '0.0.0.0/0';
|
||||
$proxyCIDRList[] = '::/0';
|
||||
}
|
||||
|
||||
return $proxyCIDRList;
|
||||
}
|
||||
|
||||
private static function validateProxyCIDR(mixed $cidr): bool
|
||||
{
|
||||
if (! is_string($cidr) || '' === $cidr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$address = $cidr;
|
||||
$mask = null;
|
||||
if (str_contains($cidr, '/')) {
|
||||
$parts = explode('/', $cidr, 2);
|
||||
assert(count($parts) >= 2);
|
||||
[$address, $mask] = $parts;
|
||||
$mask = (int) $mask;
|
||||
}
|
||||
|
||||
if (str_contains($address, ':')) {
|
||||
// is IPV6
|
||||
return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)
|
||||
&& (
|
||||
$mask === null
|
||||
|| (
|
||||
$mask <= 128
|
||||
&& $mask >= 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// is IPV4
|
||||
return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
|
||||
&& (
|
||||
$mask === null
|
||||
|| (
|
||||
$mask <= 32
|
||||
&& $mask >= 0
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
124
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/IPRange.php
vendored
Normal file
124
libraries/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/IPRange.php
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros\ServerRequestFilter;
|
||||
|
||||
use function assert;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function inet_pton;
|
||||
use function intval;
|
||||
use function ip2long;
|
||||
use function pack;
|
||||
use function sprintf;
|
||||
use function str_contains;
|
||||
use function str_pad;
|
||||
use function str_repeat;
|
||||
use function substr_compare;
|
||||
use function unpack;
|
||||
|
||||
/** @internal */
|
||||
final class IPRange
|
||||
{
|
||||
/**
|
||||
* Disable instantiation
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/** @psalm-pure */
|
||||
public static function matches(string $ip, string $cidr): bool
|
||||
{
|
||||
if (str_contains($ip, ':')) {
|
||||
return self::matchesIPv6($ip, $cidr);
|
||||
}
|
||||
|
||||
return self::matchesIPv4($ip, $cidr);
|
||||
}
|
||||
|
||||
/** @psalm-pure */
|
||||
public static function matchesIPv4(string $ip, string $cidr): bool
|
||||
{
|
||||
$mask = 32;
|
||||
$subnet = $cidr;
|
||||
|
||||
if (str_contains($cidr, '/')) {
|
||||
$parts = explode('/', $cidr, 2);
|
||||
assert(count($parts) >= 2);
|
||||
[$subnet, $mask] = $parts;
|
||||
$mask = (int) $mask;
|
||||
}
|
||||
|
||||
if ($mask < 0 || $mask > 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ip = ip2long($ip);
|
||||
$subnet = ip2long($subnet);
|
||||
if (false === $ip || false === $subnet) {
|
||||
// Invalid data
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0 === substr_compare(
|
||||
sprintf("%032b", $ip),
|
||||
sprintf("%032b", $subnet),
|
||||
0,
|
||||
$mask
|
||||
);
|
||||
}
|
||||
|
||||
/** @psalm-pure */
|
||||
public static function matchesIPv6(string $ip, string $cidr): bool
|
||||
{
|
||||
$mask = 128;
|
||||
$subnet = $cidr;
|
||||
|
||||
if (str_contains($cidr, '/')) {
|
||||
$parts = explode('/', $cidr, 2);
|
||||
assert(count($parts) >= 2);
|
||||
[$subnet, $mask] = $parts;
|
||||
$mask = (int) $mask;
|
||||
}
|
||||
|
||||
if ($mask < 0 || $mask > 128) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ip = inet_pton($ip);
|
||||
$subnet = inet_pton($subnet);
|
||||
|
||||
if (false === $ip || false === $subnet) {
|
||||
// Invalid data
|
||||
return false;
|
||||
}
|
||||
|
||||
// mask 0: if it's a valid IP, it's valid
|
||||
if ($mask === 0) {
|
||||
return (bool) unpack('n*', $ip);
|
||||
}
|
||||
|
||||
// @see http://stackoverflow.com/questions/7951061/matching-ipv6-address-to-a-cidr-subnet, MW answer
|
||||
$binMask = str_repeat("f", intval($mask / 4));
|
||||
switch ($mask % 4) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
$binMask .= "8";
|
||||
break;
|
||||
case 2:
|
||||
$binMask .= "c";
|
||||
break;
|
||||
case 3:
|
||||
$binMask .= "e";
|
||||
break;
|
||||
}
|
||||
|
||||
$binMask = str_pad($binMask, 32, '0');
|
||||
$binMask = pack("H*", $binMask);
|
||||
|
||||
return ($ip & $binMask) === $subnet;
|
||||
}
|
||||
}
|
||||
367
libraries/vendor/laminas/laminas-diactoros/src/Stream.php
vendored
Normal file
367
libraries/vendor/laminas/laminas-diactoros/src/Stream.php
vendored
Normal file
@ -0,0 +1,367 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use GdImage;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use RuntimeException;
|
||||
use Stringable;
|
||||
use Throwable;
|
||||
|
||||
use function array_key_exists;
|
||||
use function fclose;
|
||||
use function feof;
|
||||
use function fopen;
|
||||
use function fread;
|
||||
use function fseek;
|
||||
use function fstat;
|
||||
use function ftell;
|
||||
use function fwrite;
|
||||
use function get_resource_type;
|
||||
use function in_array;
|
||||
use function is_int;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
use function stream_get_contents;
|
||||
use function stream_get_meta_data;
|
||||
use function strstr;
|
||||
|
||||
use const SEEK_SET;
|
||||
|
||||
/**
|
||||
* Implementation of PSR HTTP streams
|
||||
*/
|
||||
class Stream implements StreamInterface, Stringable
|
||||
{
|
||||
/**
|
||||
* A list of allowed stream resource types that are allowed to instantiate a Stream
|
||||
*/
|
||||
private const ALLOWED_STREAM_RESOURCE_TYPES = ['gd', 'stream'];
|
||||
|
||||
/** @var resource|null */
|
||||
protected $resource;
|
||||
|
||||
/** @var string|object|resource|null */
|
||||
protected $stream;
|
||||
|
||||
/**
|
||||
* @param string|object|resource $stream
|
||||
* @param string $mode Mode with which to open stream
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function __construct($stream, string $mode = 'r')
|
||||
{
|
||||
$this->setStream($stream, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
if (! $this->isReadable()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->isSeekable()) {
|
||||
$this->rewind();
|
||||
}
|
||||
|
||||
return $this->getContents();
|
||||
} catch (RuntimeException) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
if (! $this->resource) {
|
||||
return;
|
||||
}
|
||||
|
||||
$resource = $this->detach();
|
||||
fclose($resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function detach()
|
||||
{
|
||||
$resource = $this->resource;
|
||||
$this->resource = null;
|
||||
return $resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a new stream/resource to the instance.
|
||||
*
|
||||
* @param string|object|resource $resource
|
||||
* @throws Exception\InvalidArgumentException For stream identifier that cannot be cast to a resource.
|
||||
* @throws Exception\InvalidArgumentException For non-resource stream.
|
||||
*/
|
||||
public function attach($resource, string $mode = 'r'): void
|
||||
{
|
||||
$this->setStream($resource, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize(): ?int
|
||||
{
|
||||
if (null === $this->resource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$stats = fstat($this->resource);
|
||||
if ($stats !== false) {
|
||||
return $stats['size'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function tell(): int
|
||||
{
|
||||
if (! $this->resource) {
|
||||
throw Exception\UntellableStreamException::dueToMissingResource();
|
||||
}
|
||||
|
||||
$result = ftell($this->resource);
|
||||
if (! is_int($result)) {
|
||||
throw Exception\UntellableStreamException::dueToPhpError();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function eof(): bool
|
||||
{
|
||||
if (! $this->resource) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return feof($this->resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isSeekable(): bool
|
||||
{
|
||||
if (! $this->resource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$meta = stream_get_meta_data($this->resource);
|
||||
return $meta['seekable'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function seek($offset, $whence = SEEK_SET): void
|
||||
{
|
||||
if (! $this->resource) {
|
||||
throw Exception\UnseekableStreamException::dueToMissingResource();
|
||||
}
|
||||
|
||||
if (! $this->isSeekable()) {
|
||||
throw Exception\UnseekableStreamException::dueToConfiguration();
|
||||
}
|
||||
|
||||
$result = fseek($this->resource, $offset, $whence);
|
||||
|
||||
if (0 !== $result) {
|
||||
throw Exception\UnseekableStreamException::dueToPhpError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rewind(): void
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isWritable(): bool
|
||||
{
|
||||
if (! $this->resource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$meta = stream_get_meta_data($this->resource);
|
||||
$mode = $meta['mode'];
|
||||
|
||||
return strstr($mode, 'x')
|
||||
|| strstr($mode, 'w')
|
||||
|| strstr($mode, 'c')
|
||||
|| strstr($mode, 'a')
|
||||
|| strstr($mode, '+');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($string): int
|
||||
{
|
||||
if (! $this->resource) {
|
||||
throw Exception\UnwritableStreamException::dueToMissingResource();
|
||||
}
|
||||
|
||||
if (! $this->isWritable()) {
|
||||
throw Exception\UnwritableStreamException::dueToConfiguration();
|
||||
}
|
||||
|
||||
$result = fwrite($this->resource, $string);
|
||||
|
||||
if (false === $result) {
|
||||
throw Exception\UnwritableStreamException::dueToPhpError();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isReadable(): bool
|
||||
{
|
||||
if (! $this->resource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$meta = stream_get_meta_data($this->resource);
|
||||
$mode = $meta['mode'];
|
||||
|
||||
return strstr($mode, 'r') || strstr($mode, '+');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($length): string
|
||||
{
|
||||
if (! $this->resource) {
|
||||
throw Exception\UnreadableStreamException::dueToMissingResource();
|
||||
}
|
||||
|
||||
if (! $this->isReadable()) {
|
||||
throw Exception\UnreadableStreamException::dueToConfiguration();
|
||||
}
|
||||
|
||||
$result = fread($this->resource, $length);
|
||||
|
||||
if (false === $result) {
|
||||
throw Exception\UnreadableStreamException::dueToPhpError();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContents(): string
|
||||
{
|
||||
if (! $this->isReadable()) {
|
||||
throw Exception\UnreadableStreamException::dueToConfiguration();
|
||||
}
|
||||
|
||||
$result = stream_get_contents($this->resource);
|
||||
if (false === $result) {
|
||||
throw Exception\UnreadableStreamException::dueToPhpError();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
if (null === $key) {
|
||||
return stream_get_meta_data($this->resource);
|
||||
}
|
||||
|
||||
$metadata = stream_get_meta_data($this->resource);
|
||||
if (! array_key_exists($key, $metadata)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $metadata[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the internal stream resource.
|
||||
*
|
||||
* @param string|object|resource $stream String stream target or stream resource.
|
||||
* @param string $mode Resource mode for stream target.
|
||||
* @throws Exception\InvalidArgumentException For invalid streams or resources.
|
||||
*/
|
||||
private function setStream($stream, string $mode = 'r'): void
|
||||
{
|
||||
$resource = $stream;
|
||||
|
||||
if (is_string($stream)) {
|
||||
try {
|
||||
$resource = fopen($stream, $mode);
|
||||
} catch (Throwable $error) {
|
||||
throw new Exception\RuntimeException(
|
||||
sprintf('Invalid stream reference provided: %s', $error->getMessage()),
|
||||
0,
|
||||
$error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (! $this->isValidStreamResourceType($resource)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid stream provided; must be a string stream identifier or stream resource'
|
||||
);
|
||||
}
|
||||
|
||||
if ($stream !== $resource) {
|
||||
$this->stream = $stream;
|
||||
}
|
||||
|
||||
$this->resource = $resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a resource is one of the resource types allowed to instantiate a Stream
|
||||
*
|
||||
* @param mixed $resource Stream resource.
|
||||
* @psalm-assert-if-true resource $resource
|
||||
*/
|
||||
private function isValidStreamResourceType(mixed $resource): bool
|
||||
{
|
||||
if (is_resource($resource)) {
|
||||
return in_array(get_resource_type($resource), self::ALLOWED_STREAM_RESOURCE_TYPES, true);
|
||||
}
|
||||
|
||||
if ($resource instanceof GdImage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
43
libraries/vendor/laminas/laminas-diactoros/src/StreamFactory.php
vendored
Normal file
43
libraries/vendor/laminas/laminas-diactoros/src/StreamFactory.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\StreamFactoryInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function rewind;
|
||||
|
||||
class StreamFactory implements StreamFactoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createStream(string $content = ''): StreamInterface
|
||||
{
|
||||
$resource = fopen('php://temp', 'r+');
|
||||
fwrite($resource, $content);
|
||||
rewind($resource);
|
||||
|
||||
return $this->createStreamFromResource($resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface
|
||||
{
|
||||
return new Stream($file, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createStreamFromResource($resource): StreamInterface
|
||||
{
|
||||
return new Stream($resource);
|
||||
}
|
||||
}
|
||||
234
libraries/vendor/laminas/laminas-diactoros/src/UploadedFile.php
vendored
Normal file
234
libraries/vendor/laminas/laminas-diactoros/src/UploadedFile.php
vendored
Normal file
@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
|
||||
use function dirname;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function is_dir;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function is_writable;
|
||||
use function move_uploaded_file;
|
||||
use function str_starts_with;
|
||||
use function unlink;
|
||||
|
||||
use const PHP_SAPI;
|
||||
use const UPLOAD_ERR_CANT_WRITE;
|
||||
use const UPLOAD_ERR_EXTENSION;
|
||||
use const UPLOAD_ERR_FORM_SIZE;
|
||||
use const UPLOAD_ERR_INI_SIZE;
|
||||
use const UPLOAD_ERR_NO_FILE;
|
||||
use const UPLOAD_ERR_NO_TMP_DIR;
|
||||
use const UPLOAD_ERR_OK;
|
||||
use const UPLOAD_ERR_PARTIAL;
|
||||
|
||||
class UploadedFile implements UploadedFileInterface
|
||||
{
|
||||
public const ERROR_MESSAGES = [
|
||||
UPLOAD_ERR_OK => 'There is no error, the file uploaded with success',
|
||||
UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
|
||||
UPLOAD_ERR_FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was '
|
||||
. 'specified in the HTML form',
|
||||
UPLOAD_ERR_PARTIAL => 'The uploaded file was only partially uploaded',
|
||||
UPLOAD_ERR_NO_FILE => 'No file was uploaded',
|
||||
UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder',
|
||||
UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk',
|
||||
UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the file upload.',
|
||||
];
|
||||
|
||||
private int $error;
|
||||
|
||||
private ?string $file = null;
|
||||
|
||||
private bool $moved = false;
|
||||
|
||||
/** @var null|StreamInterface */
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* @param string|resource|StreamInterface $streamOrFile
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function __construct(
|
||||
$streamOrFile,
|
||||
private int $size,
|
||||
int $errorStatus,
|
||||
private ?string $clientFilename = null,
|
||||
private ?string $clientMediaType = null
|
||||
) {
|
||||
if ($errorStatus === UPLOAD_ERR_OK) {
|
||||
if (is_string($streamOrFile)) {
|
||||
$this->file = $streamOrFile;
|
||||
}
|
||||
if (is_resource($streamOrFile)) {
|
||||
$this->stream = new Stream($streamOrFile);
|
||||
}
|
||||
|
||||
if (! $this->file && ! $this->stream) {
|
||||
if (! $streamOrFile instanceof StreamInterface) {
|
||||
throw new Exception\InvalidArgumentException('Invalid stream or file provided for UploadedFile');
|
||||
}
|
||||
$this->stream = $streamOrFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 > $errorStatus || 8 < $errorStatus) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid error status for UploadedFile; must be an UPLOAD_ERR_* constant'
|
||||
);
|
||||
}
|
||||
$this->error = $errorStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws Exception\UploadedFileAlreadyMovedException If the upload was not successful.
|
||||
*/
|
||||
public function getStream(): StreamInterface
|
||||
{
|
||||
if ($this->error !== UPLOAD_ERR_OK) {
|
||||
throw Exception\UploadedFileErrorException::dueToStreamUploadError(
|
||||
self::ERROR_MESSAGES[$this->error]
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->moved) {
|
||||
throw new Exception\UploadedFileAlreadyMovedException();
|
||||
}
|
||||
|
||||
if ($this->stream instanceof StreamInterface) {
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
$this->stream = new Stream($this->file);
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see http://php.net/is_uploaded_file
|
||||
* @see http://php.net/move_uploaded_file
|
||||
*
|
||||
* @param string $targetPath Path to which to move the uploaded file.
|
||||
* @throws Exception\UploadedFileErrorException If the upload was not successful.
|
||||
* @throws Exception\InvalidArgumentException If the $path specified is invalid.
|
||||
* @throws Exception\UploadedFileErrorException On any error during the
|
||||
* move operation, or on the second or subsequent call to the method.
|
||||
*/
|
||||
public function moveTo($targetPath): void
|
||||
{
|
||||
if ($this->moved) {
|
||||
throw new Exception\UploadedFileAlreadyMovedException('Cannot move file; already moved!');
|
||||
}
|
||||
|
||||
if ($this->error !== UPLOAD_ERR_OK) {
|
||||
throw Exception\UploadedFileErrorException::dueToStreamUploadError(
|
||||
self::ERROR_MESSAGES[$this->error]
|
||||
);
|
||||
}
|
||||
|
||||
if (! is_string($targetPath) || empty($targetPath)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid path provided for move operation; must be a non-empty string'
|
||||
);
|
||||
}
|
||||
|
||||
$targetDirectory = dirname($targetPath);
|
||||
if (! is_dir($targetDirectory) || ! is_writable($targetDirectory)) {
|
||||
throw Exception\UploadedFileErrorException::dueToUnwritableTarget($targetDirectory);
|
||||
}
|
||||
|
||||
$sapi = PHP_SAPI;
|
||||
switch (true) {
|
||||
case empty($sapi) || str_starts_with($sapi, 'cli') || str_starts_with($sapi, 'phpdbg') || ! $this->file:
|
||||
// Non-SAPI environment, or no filename present
|
||||
$this->writeFile($targetPath);
|
||||
|
||||
if ($this->stream instanceof StreamInterface) {
|
||||
$this->stream->close();
|
||||
}
|
||||
if (is_string($this->file) && file_exists($this->file)) {
|
||||
unlink($this->file);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// SAPI environment, with file present
|
||||
if (false === move_uploaded_file($this->file, $targetPath)) {
|
||||
throw Exception\UploadedFileErrorException::forUnmovableFile();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$this->moved = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return int|null The file size in bytes or null if unknown.
|
||||
*/
|
||||
public function getSize(): ?int
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see http://php.net/manual/en/features.file-upload.errors.php
|
||||
*
|
||||
* @return int One of PHP's UPLOAD_ERR_XXX constants.
|
||||
*/
|
||||
public function getError(): int
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return string|null The filename sent by the client or null if none
|
||||
* was provided.
|
||||
*/
|
||||
public function getClientFilename(): ?string
|
||||
{
|
||||
return $this->clientFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientMediaType(): ?string
|
||||
{
|
||||
return $this->clientMediaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write internal stream to given path
|
||||
*/
|
||||
private function writeFile(string $path): void
|
||||
{
|
||||
$handle = fopen($path, 'wb+');
|
||||
if (false === $handle) {
|
||||
throw Exception\UploadedFileErrorException::dueToUnwritablePath();
|
||||
}
|
||||
|
||||
$stream = $this->getStream();
|
||||
$stream->rewind();
|
||||
while (! $stream->eof()) {
|
||||
fwrite($handle, $stream->read(4096));
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
31
libraries/vendor/laminas/laminas-diactoros/src/UploadedFileFactory.php
vendored
Normal file
31
libraries/vendor/laminas/laminas-diactoros/src/UploadedFileFactory.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UploadedFileFactoryInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
|
||||
use const UPLOAD_ERR_OK;
|
||||
|
||||
class UploadedFileFactory implements UploadedFileFactoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createUploadedFile(
|
||||
StreamInterface $stream,
|
||||
?int $size = null,
|
||||
int $error = UPLOAD_ERR_OK,
|
||||
?string $clientFilename = null,
|
||||
?string $clientMediaType = null
|
||||
): UploadedFileInterface {
|
||||
if ($size === null) {
|
||||
$size = $stream->getSize();
|
||||
}
|
||||
|
||||
return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType);
|
||||
}
|
||||
}
|
||||
690
libraries/vendor/laminas/laminas-diactoros/src/Uri.php
vendored
Normal file
690
libraries/vendor/laminas/laminas-diactoros/src/Uri.php
vendored
Normal file
@ -0,0 +1,690 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use SensitiveParameter;
|
||||
use Stringable;
|
||||
|
||||
use function array_keys;
|
||||
use function explode;
|
||||
use function gettype;
|
||||
use function implode;
|
||||
use function is_float;
|
||||
use function is_numeric;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function ltrim;
|
||||
use function parse_url;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function preg_replace_callback;
|
||||
use function rawurlencode;
|
||||
use function sprintf;
|
||||
use function str_contains;
|
||||
use function str_split;
|
||||
use function str_starts_with;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* Implementation of Psr\Http\UriInterface.
|
||||
*
|
||||
* Provides a value object representing a URI for HTTP requests.
|
||||
*
|
||||
* Instances of this class are considered immutable; all methods that
|
||||
* might change state are implemented such that they retain the internal
|
||||
* state of the current instance and return a new instance that contains the
|
||||
* changed state.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class Uri implements UriInterface, Stringable
|
||||
{
|
||||
/**
|
||||
* Sub-delimiters used in user info, query strings and fragments.
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
public const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;=';
|
||||
|
||||
/**
|
||||
* Unreserved characters used in user info, paths, query strings, and fragments.
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
public const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~\pL';
|
||||
|
||||
/** @var int[] Array indexed by valid scheme names to their corresponding ports. */
|
||||
protected $allowedSchemes = [
|
||||
'http' => 80,
|
||||
'https' => 443,
|
||||
];
|
||||
|
||||
private string $scheme = '';
|
||||
|
||||
private string $userInfo = '';
|
||||
|
||||
private string $host = '';
|
||||
|
||||
private ?int $port = null;
|
||||
|
||||
private string $path = '';
|
||||
|
||||
private string $query = '';
|
||||
|
||||
private string $fragment = '';
|
||||
|
||||
/**
|
||||
* generated uri string cache
|
||||
*/
|
||||
private ?string $uriString = null;
|
||||
|
||||
public function __construct(string $uri = '')
|
||||
{
|
||||
if ('' === $uri) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->parseUri($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operations to perform on clone.
|
||||
*
|
||||
* Since cloning usually is for purposes of mutation, we reset the
|
||||
* $uriString property so it will be re-calculated.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->uriString = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
if (null !== $this->uriString) {
|
||||
return $this->uriString;
|
||||
}
|
||||
|
||||
/** @psalm-suppress ImpureMethodCall, InaccessibleProperty */
|
||||
$this->uriString = static::createUriString(
|
||||
$this->scheme,
|
||||
$this->getAuthority(),
|
||||
$this->path, // Absolute URIs should use a "/" for an empty path
|
||||
$this->query,
|
||||
$this->fragment
|
||||
);
|
||||
|
||||
return $this->uriString;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getScheme(): string
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAuthority(): string
|
||||
{
|
||||
if ('' === $this->host) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$authority = $this->host;
|
||||
if ('' !== $this->userInfo) {
|
||||
$authority = $this->userInfo . '@' . $authority;
|
||||
}
|
||||
|
||||
if ($this->isNonStandardPort($this->scheme, $this->host, $this->port)) {
|
||||
$authority .= ':' . $this->port;
|
||||
}
|
||||
|
||||
return $authority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the user-info part of the URI.
|
||||
*
|
||||
* This value is percent-encoded, per RFC 3986 Section 3.2.1.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getUserInfo(): string
|
||||
{
|
||||
return $this->userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHost(): string
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPort(): ?int
|
||||
{
|
||||
return $this->isNonStandardPort($this->scheme, $this->host, $this->port)
|
||||
? $this->port
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPath(): string
|
||||
{
|
||||
if ('' === $this->path) {
|
||||
// No path
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
if ($this->path[0] !== '/') {
|
||||
// Relative path
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
// Ensure only one leading slash, to prevent XSS attempts.
|
||||
return '/' . ltrim($this->path, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuery(): string
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFragment(): string
|
||||
{
|
||||
return $this->fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withScheme($scheme): UriInterface
|
||||
{
|
||||
if (! is_string($scheme)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a string argument; received %s',
|
||||
__METHOD__,
|
||||
is_object($scheme) ? $scheme::class : gettype($scheme)
|
||||
));
|
||||
}
|
||||
|
||||
$scheme = $this->filterScheme($scheme);
|
||||
|
||||
if ($scheme === $this->scheme) {
|
||||
// Do nothing if no change was made.
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->scheme = $scheme;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
// The following rule is buggy for parameters attributes
|
||||
// phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHintSpacing.NoSpaceBetweenTypeHintAndParameter
|
||||
|
||||
/**
|
||||
* Create and return a new instance containing the provided user credentials.
|
||||
*
|
||||
* The value will be percent-encoded in the new instance, but with measures
|
||||
* taken to prevent double-encoding.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withUserInfo(
|
||||
$user,
|
||||
#[SensitiveParameter]
|
||||
$password = null
|
||||
): UriInterface {
|
||||
if (! is_string($user)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a string user argument; received %s',
|
||||
__METHOD__,
|
||||
is_object($user) ? $user::class : gettype($user)
|
||||
));
|
||||
}
|
||||
if (null !== $password && ! is_string($password)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a string or null password argument; received %s',
|
||||
__METHOD__,
|
||||
is_object($password) ? $password::class : gettype($password)
|
||||
));
|
||||
}
|
||||
|
||||
$info = $this->filterUserInfoPart($user);
|
||||
if (null !== $password) {
|
||||
$info .= ':' . $this->filterUserInfoPart($password);
|
||||
}
|
||||
|
||||
if ($info === $this->userInfo) {
|
||||
// Do nothing if no change was made.
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->userInfo = $info;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
// phpcs:enable SlevomatCodingStandard.TypeHints.ParameterTypeHintSpacing.NoSpaceBetweenTypeHintAndParameter
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withHost($host): UriInterface
|
||||
{
|
||||
if (! is_string($host)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a string argument; received %s',
|
||||
__METHOD__,
|
||||
is_object($host) ? $host::class : gettype($host)
|
||||
));
|
||||
}
|
||||
|
||||
if ($host === $this->host) {
|
||||
// Do nothing if no change was made.
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->host = strtolower($host);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withPort($port): UriInterface
|
||||
{
|
||||
if ($port !== null) {
|
||||
if (! is_numeric($port) || is_float($port)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Invalid port "%s" specified; must be an integer, an integer string, or null',
|
||||
is_object($port) ? $port::class : gettype($port)
|
||||
));
|
||||
}
|
||||
|
||||
$port = (int) $port;
|
||||
}
|
||||
|
||||
if ($port === $this->port) {
|
||||
// Do nothing if no change was made.
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($port !== null && ($port < 1 || $port > 65535)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Invalid port "%d" specified; must be a valid TCP/UDP port',
|
||||
$port
|
||||
));
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->port = $port;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withPath($path): UriInterface
|
||||
{
|
||||
if (! is_string($path)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid path provided; must be a string'
|
||||
);
|
||||
}
|
||||
|
||||
if (str_contains($path, '?')) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid path provided; must not contain a query string'
|
||||
);
|
||||
}
|
||||
|
||||
if (str_contains($path, '#')) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Invalid path provided; must not contain a URI fragment'
|
||||
);
|
||||
}
|
||||
|
||||
$path = $this->filterPath($path);
|
||||
|
||||
if ($path === $this->path) {
|
||||
// Do nothing if no change was made.
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->path = $path;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withQuery($query): UriInterface
|
||||
{
|
||||
if (! is_string($query)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Query string must be a string'
|
||||
);
|
||||
}
|
||||
|
||||
if (str_contains($query, '#')) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'Query string must not include a URI fragment'
|
||||
);
|
||||
}
|
||||
|
||||
$query = $this->filterQuery($query);
|
||||
|
||||
if ($query === $this->query) {
|
||||
// Do nothing if no change was made.
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->query = $query;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withFragment($fragment): UriInterface
|
||||
{
|
||||
if (! is_string($fragment)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a string argument; received %s',
|
||||
__METHOD__,
|
||||
is_object($fragment) ? $fragment::class : gettype($fragment)
|
||||
));
|
||||
}
|
||||
|
||||
$fragment = $this->filterFragment($fragment);
|
||||
|
||||
if ($fragment === $this->fragment) {
|
||||
// Do nothing if no change was made.
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->fragment = $fragment;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a URI into its parts, and set the properties
|
||||
*
|
||||
* @psalm-suppress InaccessibleProperty Method is only called in {@see Uri::__construct} and thus immutability is
|
||||
* still given.
|
||||
*/
|
||||
private function parseUri(string $uri): void
|
||||
{
|
||||
$parts = parse_url($uri);
|
||||
|
||||
if (false === $parts) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
'The source URI string appears to be malformed'
|
||||
);
|
||||
}
|
||||
|
||||
$this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : '';
|
||||
$this->userInfo = isset($parts['user']) ? $this->filterUserInfoPart($parts['user']) : '';
|
||||
$this->host = isset($parts['host']) ? strtolower($parts['host']) : '';
|
||||
$this->port = $parts['port'] ?? null;
|
||||
$this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : '';
|
||||
$this->query = isset($parts['query']) ? $this->filterQuery($parts['query']) : '';
|
||||
$this->fragment = isset($parts['fragment']) ? $this->filterFragment($parts['fragment']) : '';
|
||||
|
||||
if (isset($parts['pass'])) {
|
||||
$this->userInfo .= ':' . $parts['pass'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a URI string from its various parts
|
||||
*/
|
||||
private static function createUriString(
|
||||
string $scheme,
|
||||
string $authority,
|
||||
string $path,
|
||||
string $query,
|
||||
string $fragment
|
||||
): string {
|
||||
$uri = '';
|
||||
|
||||
if ('' !== $scheme) {
|
||||
$uri .= sprintf('%s:', $scheme);
|
||||
}
|
||||
|
||||
if ('' !== $authority) {
|
||||
$uri .= '//' . $authority;
|
||||
}
|
||||
|
||||
if ('' !== $path && ! str_starts_with($path, '/')) {
|
||||
$path = '/' . $path;
|
||||
}
|
||||
|
||||
$uri .= $path;
|
||||
|
||||
if ('' !== $query) {
|
||||
$uri .= sprintf('?%s', $query);
|
||||
}
|
||||
|
||||
if ('' !== $fragment) {
|
||||
$uri .= sprintf('#%s', $fragment);
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a given port non-standard for the current scheme?
|
||||
*/
|
||||
private function isNonStandardPort(string $scheme, string $host, ?int $port): bool
|
||||
{
|
||||
if ('' === $scheme) {
|
||||
return '' === $host || null !== $port;
|
||||
}
|
||||
|
||||
if ('' === $host || null === $port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! isset($this->allowedSchemes[$scheme]) || $port !== $this->allowedSchemes[$scheme];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the scheme to ensure it is a valid scheme.
|
||||
*
|
||||
* @param string $scheme Scheme name.
|
||||
* @return string Filtered scheme.
|
||||
*/
|
||||
private function filterScheme(string $scheme): string
|
||||
{
|
||||
$scheme = strtolower($scheme);
|
||||
$scheme = preg_replace('#:(//)?$#', '', $scheme);
|
||||
|
||||
if ('' === $scheme) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (! isset($this->allowedSchemes[$scheme])) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'Unsupported scheme "%s"; must be any empty string or in the set (%s)',
|
||||
$scheme,
|
||||
implode(', ', array_keys($this->allowedSchemes))
|
||||
));
|
||||
}
|
||||
|
||||
return $scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a part of user info in a URI to ensure it is properly encoded.
|
||||
*/
|
||||
private function filterUserInfoPart(string $part): string
|
||||
{
|
||||
$part = $this->filterInvalidUtf8($part);
|
||||
|
||||
/**
|
||||
* @psalm-suppress ImpureFunctionCall Even tho the callback targets this immutable class,
|
||||
* psalm reports an issue here.
|
||||
* Note the addition of `%` to initial charset; this allows `|` portion
|
||||
* to match and thus prevent double-encoding.
|
||||
*/
|
||||
return preg_replace_callback(
|
||||
'/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/u',
|
||||
[$this, 'urlEncodeChar'],
|
||||
$part
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the path of a URI to ensure it is properly encoded.
|
||||
*/
|
||||
private function filterPath(string $path): string
|
||||
{
|
||||
$path = $this->filterInvalidUtf8($path);
|
||||
|
||||
/**
|
||||
* @psalm-suppress ImpureFunctionCall Even tho the callback targets this immutable class,
|
||||
* psalm reports an issue here.
|
||||
*/
|
||||
return preg_replace_callback(
|
||||
'/(?:[^' . self::CHAR_UNRESERVED . ')(:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/u',
|
||||
[$this, 'urlEncodeChar'],
|
||||
$path
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode invalid UTF-8 characters in given string. All other characters are unchanged.
|
||||
*/
|
||||
private function filterInvalidUtf8(string $string): string
|
||||
{
|
||||
// check if given string contains only valid UTF-8 characters
|
||||
if (preg_match('//u', $string)) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
$letters = str_split($string);
|
||||
foreach ($letters as $i => $letter) {
|
||||
if (! preg_match('//u', $letter)) {
|
||||
$letters[$i] = $this->urlEncodeChar([$letter]);
|
||||
}
|
||||
}
|
||||
|
||||
return implode('', $letters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a query string to ensure it is propertly encoded.
|
||||
*
|
||||
* Ensures that the values in the query string are properly urlencoded.
|
||||
*/
|
||||
private function filterQuery(string $query): string
|
||||
{
|
||||
if ('' !== $query && str_starts_with($query, '?')) {
|
||||
$query = substr($query, 1);
|
||||
}
|
||||
|
||||
$parts = explode('&', $query);
|
||||
foreach ($parts as $index => $part) {
|
||||
[$key, $value] = $this->splitQueryValue($part);
|
||||
if ($value === null) {
|
||||
$parts[$index] = $this->filterQueryOrFragment($key);
|
||||
continue;
|
||||
}
|
||||
$parts[$index] = sprintf(
|
||||
'%s=%s',
|
||||
$this->filterQueryOrFragment($key),
|
||||
$this->filterQueryOrFragment($value)
|
||||
);
|
||||
}
|
||||
|
||||
return implode('&', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a query value into a key/value tuple.
|
||||
*
|
||||
* @return array A value with exactly two elements, key and value
|
||||
*/
|
||||
private function splitQueryValue(string $value): array
|
||||
{
|
||||
$data = explode('=', $value, 2);
|
||||
if (! isset($data[1])) {
|
||||
$data[] = null;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a fragment value to ensure it is properly encoded.
|
||||
*/
|
||||
private function filterFragment(string $fragment): string
|
||||
{
|
||||
if ('' !== $fragment && str_starts_with($fragment, '#')) {
|
||||
$fragment = '%23' . substr($fragment, 1);
|
||||
}
|
||||
|
||||
return $this->filterQueryOrFragment($fragment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a query string key or value, or a fragment.
|
||||
*/
|
||||
private function filterQueryOrFragment(string $value): string
|
||||
{
|
||||
$value = $this->filterInvalidUtf8($value);
|
||||
|
||||
/**
|
||||
* @psalm-suppress ImpureFunctionCall Even tho the callback targets this immutable class,
|
||||
* psalm reports an issue here.
|
||||
*/
|
||||
return preg_replace_callback(
|
||||
'/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/u',
|
||||
[$this, 'urlEncodeChar'],
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL encode a character returned by a regex.
|
||||
*/
|
||||
private function urlEncodeChar(array $matches): string
|
||||
{
|
||||
return rawurlencode($matches[0]);
|
||||
}
|
||||
}
|
||||
252
libraries/vendor/laminas/laminas-diactoros/src/UriFactory.php
vendored
Normal file
252
libraries/vendor/laminas/laminas-diactoros/src/UriFactory.php
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\UriFactoryInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
use function array_change_key_case;
|
||||
use function array_key_exists;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function gettype;
|
||||
use function implode;
|
||||
use function is_bool;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
use function ltrim;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function sprintf;
|
||||
use function str_contains;
|
||||
use function strlen;
|
||||
use function strrpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
|
||||
use const CASE_LOWER;
|
||||
|
||||
class UriFactory implements UriFactoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createUri(string $uri = ''): UriInterface
|
||||
{
|
||||
return new Uri($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Uri instance based on the headers and $_SERVER data.
|
||||
*
|
||||
* @param array<non-empty-string, list<string>|int|float|string> $server SAPI parameters
|
||||
* @param array<string, string|list<string>> $headers
|
||||
*/
|
||||
public static function createFromSapi(array $server, array $headers): Uri
|
||||
{
|
||||
$uri = new Uri('');
|
||||
|
||||
$isHttps = false;
|
||||
if (array_key_exists('HTTPS', $server)) {
|
||||
$isHttps = self::marshalHttpsValue($server['HTTPS']);
|
||||
} elseif (array_key_exists('https', $server)) {
|
||||
$isHttps = self::marshalHttpsValue($server['https']);
|
||||
}
|
||||
$uri = $uri->withScheme($isHttps ? 'https' : 'http');
|
||||
|
||||
[$host, $port] = self::marshalHostAndPort($server, $headers);
|
||||
if (! empty($host)) {
|
||||
$uri = $uri->withHost($host);
|
||||
if (! empty($port)) {
|
||||
$uri = $uri->withPort($port);
|
||||
}
|
||||
}
|
||||
|
||||
$path = self::marshalRequestPath($server);
|
||||
|
||||
// Strip query string
|
||||
$path = explode('?', $path, 2)[0];
|
||||
|
||||
$query = '';
|
||||
if (isset($server['QUERY_STRING']) && is_scalar($server['QUERY_STRING'])) {
|
||||
$query = ltrim((string) $server['QUERY_STRING'], '?');
|
||||
}
|
||||
|
||||
$fragment = '';
|
||||
if (str_contains($path, '#')) {
|
||||
$parts = explode('#', $path, 2);
|
||||
assert(count($parts) >= 2);
|
||||
[$path, $fragment] = $parts;
|
||||
}
|
||||
|
||||
return $uri
|
||||
->withPath($path)
|
||||
->withFragment($fragment)
|
||||
->withQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a header value from an array of headers using a case-insensitive lookup.
|
||||
*
|
||||
* @template T
|
||||
* @param array<string, string|list<string>> $headers Key/value header pairs
|
||||
* @param T $default Default value to return if header not found
|
||||
* @return string|T
|
||||
*/
|
||||
private static function getHeaderFromArray(string $name, array $headers, $default = null)
|
||||
{
|
||||
$header = strtolower($name);
|
||||
$headers = array_change_key_case($headers, CASE_LOWER);
|
||||
if (! array_key_exists($header, $headers)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (is_string($headers[$header])) {
|
||||
return $headers[$header];
|
||||
}
|
||||
|
||||
return implode(', ', $headers[$header]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshal the host and port from the PHP environment.
|
||||
*
|
||||
* @param array<string, string|list<string>> $headers
|
||||
* @return array{string, int|null} Array of two items, host and port,
|
||||
* in that order (can be passed to a list() operation).
|
||||
*/
|
||||
private static function marshalHostAndPort(array $server, array $headers): array
|
||||
{
|
||||
/** @var array{string, null} $defaults */
|
||||
static $defaults = ['', null];
|
||||
|
||||
$host = self::getHeaderFromArray('host', $headers, false);
|
||||
if ($host !== false) {
|
||||
// Ignore obviously malformed host headers:
|
||||
// - Whitespace is invalid within a hostname and break the URI representation within HTTP.
|
||||
// non-printable characters other than SPACE and TAB are already rejected by HeaderSecurity.
|
||||
// - A comma indicates that multiple host headers have been sent which is not legal
|
||||
// and might be used in an attack where a load balancer sees a different host header
|
||||
// than Diactoros.
|
||||
if (! preg_match('/[\\t ,]/', $host)) {
|
||||
return self::marshalHostAndPortFromHeader($host);
|
||||
}
|
||||
}
|
||||
|
||||
if (! isset($server['SERVER_NAME'])) {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
$host = (string) $server['SERVER_NAME'];
|
||||
$port = isset($server['SERVER_PORT']) ? (int) $server['SERVER_PORT'] : null;
|
||||
|
||||
if (
|
||||
! isset($server['SERVER_ADDR'])
|
||||
|| ! preg_match('/^\[[0-9a-fA-F\:]+\]$/', $host)
|
||||
) {
|
||||
return [$host, $port];
|
||||
}
|
||||
|
||||
// Misinterpreted IPv6-Address
|
||||
// Reported for Safari on Windows
|
||||
return self::marshalIpv6HostAndPort($server, $port);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{string, int|null} Array of two items, host and port,
|
||||
* in that order (can be passed to a list() operation).
|
||||
*/
|
||||
private static function marshalIpv6HostAndPort(array $server, ?int $port): array
|
||||
{
|
||||
$host = '[' . (string) $server['SERVER_ADDR'] . ']';
|
||||
$port = $port ?: 80;
|
||||
$portSeparatorPos = strrpos($host, ':');
|
||||
|
||||
if (false === $portSeparatorPos) {
|
||||
return [$host, $port];
|
||||
}
|
||||
|
||||
if ($port . ']' === substr($host, $portSeparatorPos + 1)) {
|
||||
// The last digit of the IPv6-Address has been taken as port
|
||||
// Unset the port so the default port can be used
|
||||
$port = null;
|
||||
}
|
||||
return [$host, $port];
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the path for the request
|
||||
*
|
||||
* Looks at a variety of criteria in order to attempt to autodetect the base
|
||||
* request path, including:
|
||||
*
|
||||
* - IIS7 UrlRewrite environment
|
||||
* - REQUEST_URI
|
||||
* - ORIG_PATH_INFO
|
||||
*/
|
||||
private static function marshalRequestPath(array $server): string
|
||||
{
|
||||
// IIS7 with URL Rewrite: make sure we get the unencoded url
|
||||
// (double slash problem).
|
||||
/** @var string|array<string>|null $iisUrlRewritten */
|
||||
$iisUrlRewritten = $server['IIS_WasUrlRewritten'] ?? null;
|
||||
/** @var string|array<string> $unencodedUrl */
|
||||
$unencodedUrl = $server['UNENCODED_URL'] ?? '';
|
||||
if ('1' === $iisUrlRewritten && is_string($unencodedUrl) && '' !== $unencodedUrl) {
|
||||
return $unencodedUrl;
|
||||
}
|
||||
|
||||
/** @var string|array<string>|null $requestUri */
|
||||
$requestUri = $server['REQUEST_URI'] ?? null;
|
||||
|
||||
if (is_string($requestUri)) {
|
||||
return preg_replace('#^[^/:]+://[^/]+#', '', $requestUri);
|
||||
}
|
||||
|
||||
$origPathInfo = $server['ORIG_PATH_INFO'] ?? '';
|
||||
if (! is_string($origPathInfo) || '' === $origPathInfo) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
return $origPathInfo;
|
||||
}
|
||||
|
||||
private static function marshalHttpsValue(mixed $https): bool
|
||||
{
|
||||
if (is_bool($https)) {
|
||||
return $https;
|
||||
}
|
||||
|
||||
if (! is_string($https)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'SAPI HTTPS value MUST be a string or boolean; received %s',
|
||||
gettype($https)
|
||||
));
|
||||
}
|
||||
|
||||
return 'on' === strtolower($https);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @return array{string, int|null} Array of two items, host and port, in that order (can be
|
||||
* passed to a list() operation).
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public static function marshalHostAndPortFromHeader(string $host): array
|
||||
{
|
||||
$port = null;
|
||||
|
||||
// works for regname, IPv4 & IPv6
|
||||
if (preg_match('|\:(\d+)$|', $host, $matches)) {
|
||||
$host = substr($host, 0, -1 * (strlen($matches[1]) + 1));
|
||||
$port = (int) $matches[1];
|
||||
}
|
||||
|
||||
return [$host, $port];
|
||||
}
|
||||
}
|
||||
18
libraries/vendor/laminas/laminas-diactoros/src/functions/create_uploaded_file.legacy.php
vendored
Normal file
18
libraries/vendor/laminas/laminas-diactoros/src/functions/create_uploaded_file.legacy.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use Laminas\Diactoros\UploadedFile;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\createUploadedFile as laminas_createUploadedFile;
|
||||
|
||||
/**
|
||||
* @deprecated Use Laminas\Diactoros\createUploadedFile instead
|
||||
*/
|
||||
function createUploadedFile(array $spec): UploadedFile
|
||||
{
|
||||
return laminas_createUploadedFile(...func_get_args());
|
||||
}
|
||||
37
libraries/vendor/laminas/laminas-diactoros/src/functions/create_uploaded_file.php
vendored
Normal file
37
libraries/vendor/laminas/laminas-diactoros/src/functions/create_uploaded_file.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Create an uploaded file instance from an array of values.
|
||||
*
|
||||
* @param array $spec A single $_FILES entry.
|
||||
* @throws Exception\InvalidArgumentException If one or more of the tmp_name,
|
||||
* size, or error keys are missing from $spec.
|
||||
*/
|
||||
function createUploadedFile(array $spec): UploadedFile
|
||||
{
|
||||
if (
|
||||
! isset($spec['tmp_name'])
|
||||
|| ! isset($spec['size'])
|
||||
|| ! isset($spec['error'])
|
||||
) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'$spec provided to %s MUST contain each of the keys "tmp_name",'
|
||||
. ' "size", and "error"; one or more were missing',
|
||||
__FUNCTION__
|
||||
));
|
||||
}
|
||||
|
||||
return new UploadedFile(
|
||||
$spec['tmp_name'],
|
||||
(int) $spec['size'],
|
||||
$spec['error'],
|
||||
$spec['name'] ?? null,
|
||||
$spec['type'] ?? null
|
||||
);
|
||||
}
|
||||
16
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.legacy.php
vendored
Normal file
16
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.legacy.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\marshalHeadersFromSapi as laminas_marshalHeadersFromSapi;
|
||||
|
||||
/**
|
||||
* @deprecated Use Laminas\Diactoros\marshalHeadersFromSapi instead
|
||||
*/
|
||||
function marshalHeadersFromSapi(array $server): array
|
||||
{
|
||||
return laminas_marshalHeadersFromSapi(...func_get_args());
|
||||
}
|
||||
67
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.php
vendored
Normal file
67
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use function array_key_exists;
|
||||
use function is_string;
|
||||
use function str_starts_with;
|
||||
use function strtolower;
|
||||
use function strtr;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* @param array $server Values obtained from the SAPI (generally `$_SERVER`).
|
||||
* @return array Header/value pairs
|
||||
*/
|
||||
function marshalHeadersFromSapi(array $server): array
|
||||
{
|
||||
$contentHeaderLookup = isset($server['LAMINAS_DIACTOROS_STRICT_CONTENT_HEADER_LOOKUP'])
|
||||
? static function (string $key): bool {
|
||||
static $contentHeaders = [
|
||||
'CONTENT_TYPE' => true,
|
||||
'CONTENT_LENGTH' => true,
|
||||
'CONTENT_MD5' => true,
|
||||
];
|
||||
return isset($contentHeaders[$key]);
|
||||
}
|
||||
: static fn(string $key): bool => str_starts_with($key, 'CONTENT_');
|
||||
|
||||
$headers = [];
|
||||
foreach ($server as $key => $value) {
|
||||
if (! is_string($key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($value === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Apache prefixes environment variables with REDIRECT_
|
||||
// if they are added by rewrite rules
|
||||
if (str_starts_with($key, 'REDIRECT_')) {
|
||||
$key = substr($key, 9);
|
||||
|
||||
// We will not overwrite existing variables with the
|
||||
// prefixed versions, though
|
||||
if (array_key_exists($key, $server)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (str_starts_with($key, 'HTTP_')) {
|
||||
$name = strtr(strtolower(substr($key, 5)), '_', '-');
|
||||
$headers[$name] = $value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($contentHeaderLookup($key)) {
|
||||
$name = strtr(strtolower($key), '_', '-');
|
||||
$headers[$name] = $value;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
16
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.legacy.php
vendored
Normal file
16
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.legacy.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\marshalMethodFromSapi as laminas_marshalMethodFromSapi;
|
||||
|
||||
/**
|
||||
* @deprecated Use Laminas\Diactoros\marshalMethodFromSapi instead
|
||||
*/
|
||||
function marshalMethodFromSapi(array $server): string
|
||||
{
|
||||
return laminas_marshalMethodFromSapi(...func_get_args());
|
||||
}
|
||||
13
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.php
vendored
Normal file
13
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
/**
|
||||
* Retrieve the request method from the SAPI parameters.
|
||||
*/
|
||||
function marshalMethodFromSapi(array $server): string
|
||||
{
|
||||
return $server['REQUEST_METHOD'] ?? 'GET';
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\marshalProtocolVersionFromSapi as laminas_marshalProtocolVersionFromSapi;
|
||||
|
||||
/**
|
||||
* @deprecated Use Laminas\Diactoros\marshalProtocolVersionFromSapi instead
|
||||
*/
|
||||
function marshalProtocolVersionFromSapi(array $server): string
|
||||
{
|
||||
return laminas_marshalProtocolVersionFromSapi(...func_get_args());
|
||||
}
|
||||
28
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_protocol_version_from_sapi.php
vendored
Normal file
28
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_protocol_version_from_sapi.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use function preg_match;
|
||||
|
||||
/**
|
||||
* Return HTTP protocol version (X.Y) as discovered within a `$_SERVER` array.
|
||||
*
|
||||
* @throws Exception\UnrecognizedProtocolVersionException If the
|
||||
* $server['SERVER_PROTOCOL'] value is malformed.
|
||||
*/
|
||||
function marshalProtocolVersionFromSapi(array $server): string
|
||||
{
|
||||
if (! isset($server['SERVER_PROTOCOL'])) {
|
||||
return '1.1';
|
||||
}
|
||||
|
||||
if (! preg_match('#^(HTTP/)?(?P<version>[1-9]\d*(?:\.\d)?)$#', $server['SERVER_PROTOCOL'], $matches)) {
|
||||
throw Exception\UnrecognizedProtocolVersionException::forVersion(
|
||||
(string) $server['SERVER_PROTOCOL']
|
||||
);
|
||||
}
|
||||
|
||||
return $matches['version'];
|
||||
}
|
||||
18
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.legacy.php
vendored
Normal file
18
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.legacy.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use Laminas\Diactoros\Uri;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\marshalUriFromSapi as laminas_marshalUriFromSapi;
|
||||
|
||||
/**
|
||||
* @deprecated Use Laminas\Diactoros\marshalUriFromSapi instead
|
||||
*/
|
||||
function marshalUriFromSapi(array $server, array $headers): Uri
|
||||
{
|
||||
return laminas_marshalUriFromSapi(...func_get_args());
|
||||
}
|
||||
233
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php
vendored
Normal file
233
libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use function array_change_key_case;
|
||||
use function array_key_exists;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function gettype;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_string;
|
||||
use function ltrim;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function sprintf;
|
||||
use function str_contains;
|
||||
use function strlen;
|
||||
use function strrpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
|
||||
use const CASE_LOWER;
|
||||
|
||||
/**
|
||||
* Marshal a Uri instance based on the values presnt in the $_SERVER array and headers.
|
||||
*
|
||||
* @deprecated This function is deprecated as of 2.11.1, and will be removed in
|
||||
* 3.0.0. As of 2.11.1, it is no longer used internally.
|
||||
*
|
||||
* @param array $server SAPI parameters
|
||||
* @param array $headers HTTP request headers
|
||||
*/
|
||||
function marshalUriFromSapi(array $server, array $headers): Uri
|
||||
{
|
||||
/**
|
||||
* Retrieve a header value from an array of headers using a case-insensitive lookup.
|
||||
*
|
||||
* @param array $headers Key/value header pairs
|
||||
* @param mixed $default Default value to return if header not found
|
||||
* @return mixed
|
||||
*/
|
||||
$getHeaderFromArray = static function (string $name, array $headers, $default = null) {
|
||||
$header = strtolower($name);
|
||||
$headers = array_change_key_case($headers, CASE_LOWER);
|
||||
if (array_key_exists($header, $headers)) {
|
||||
return is_array($headers[$header]) ? implode(', ', $headers[$header]) : $headers[$header];
|
||||
}
|
||||
|
||||
return $default;
|
||||
};
|
||||
|
||||
/**
|
||||
* Marshal the host and port from HTTP headers and/or the PHP environment.
|
||||
*
|
||||
* @return array Array of two items, host and port, in that order (can be
|
||||
* passed to a list() operation).
|
||||
*/
|
||||
$marshalHostAndPort = static function (array $headers, array $server) use ($getHeaderFromArray): array {
|
||||
/**
|
||||
* @param string|array $host
|
||||
* @return array Array of two items, host and port, in that order (can be
|
||||
* passed to a list() operation).
|
||||
*/
|
||||
$marshalHostAndPortFromHeader = static function ($host) {
|
||||
if (is_array($host)) {
|
||||
$host = implode(', ', $host);
|
||||
}
|
||||
|
||||
$port = null;
|
||||
|
||||
// works for regname, IPv4 & IPv6
|
||||
if (preg_match('|\:(\d+)$|', $host, $matches)) {
|
||||
$host = substr($host, 0, -1 * (strlen($matches[1]) + 1));
|
||||
$port = (int) $matches[1];
|
||||
}
|
||||
|
||||
return [$host, $port];
|
||||
};
|
||||
|
||||
/**
|
||||
* @return array Array of two items, host and port, in that order (can be
|
||||
* passed to a list() operation).
|
||||
*/
|
||||
$marshalIpv6HostAndPort = static function (array $server, ?int $port): array {
|
||||
$host = '[' . $server['SERVER_ADDR'] . ']';
|
||||
$port = $port ?: 80;
|
||||
if ($port . ']' === substr($host, strrpos($host, ':') + 1)) {
|
||||
// The last digit of the IPv6-Address has been taken as port
|
||||
// Unset the port so the default port can be used
|
||||
$port = null;
|
||||
}
|
||||
return [$host, $port];
|
||||
};
|
||||
|
||||
static $defaults = ['', null];
|
||||
|
||||
$forwardedHost = $getHeaderFromArray('x-forwarded-host', $headers, false);
|
||||
if ($forwardedHost !== false) {
|
||||
return $marshalHostAndPortFromHeader($forwardedHost);
|
||||
}
|
||||
|
||||
$host = $getHeaderFromArray('host', $headers, false);
|
||||
if ($host !== false) {
|
||||
return $marshalHostAndPortFromHeader($host);
|
||||
}
|
||||
|
||||
if (! isset($server['SERVER_NAME'])) {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
$host = $server['SERVER_NAME'];
|
||||
$port = isset($server['SERVER_PORT']) ? (int) $server['SERVER_PORT'] : null;
|
||||
|
||||
if (
|
||||
! isset($server['SERVER_ADDR'])
|
||||
|| ! preg_match('/^\[[0-9a-fA-F\:]+\]$/', $host)
|
||||
) {
|
||||
return [$host, $port];
|
||||
}
|
||||
|
||||
// Misinterpreted IPv6-Address
|
||||
// Reported for Safari on Windows
|
||||
return $marshalIpv6HostAndPort($server, $port);
|
||||
};
|
||||
|
||||
/**
|
||||
* Detect the path for the request
|
||||
*
|
||||
* Looks at a variety of criteria in order to attempt to autodetect the base
|
||||
* request path, including:
|
||||
*
|
||||
* - IIS7 UrlRewrite environment
|
||||
* - REQUEST_URI
|
||||
* - ORIG_PATH_INFO
|
||||
*
|
||||
* From Laminas\Http\PhpEnvironment\Request class
|
||||
*/
|
||||
$marshalRequestPath = static function (array $server): string {
|
||||
// IIS7 with URL Rewrite: make sure we get the unencoded url
|
||||
// (double slash problem).
|
||||
$iisUrlRewritten = $server['IIS_WasUrlRewritten'] ?? null;
|
||||
$unencodedUrl = $server['UNENCODED_URL'] ?? '';
|
||||
if ('1' === $iisUrlRewritten && ! empty($unencodedUrl)) {
|
||||
return $unencodedUrl;
|
||||
}
|
||||
|
||||
$requestUri = $server['REQUEST_URI'] ?? null;
|
||||
|
||||
if ($requestUri !== null) {
|
||||
return preg_replace('#^[^/:]+://[^/]+#', '', $requestUri);
|
||||
}
|
||||
|
||||
$origPathInfo = $server['ORIG_PATH_INFO'] ?? null;
|
||||
if (empty($origPathInfo)) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
return $origPathInfo;
|
||||
};
|
||||
|
||||
$uri = new Uri('');
|
||||
|
||||
// URI scheme
|
||||
$scheme = 'http';
|
||||
$marshalHttpsValue = static function ($https): bool {
|
||||
if (is_bool($https)) {
|
||||
return $https;
|
||||
}
|
||||
|
||||
if (! is_string($https)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'SAPI HTTPS value MUST be a string or boolean; received %s',
|
||||
gettype($https)
|
||||
));
|
||||
}
|
||||
|
||||
return 'on' === strtolower($https);
|
||||
};
|
||||
if (array_key_exists('HTTPS', $server)) {
|
||||
$https = $marshalHttpsValue($server['HTTPS']);
|
||||
} elseif (array_key_exists('https', $server)) {
|
||||
$https = $marshalHttpsValue($server['https']);
|
||||
} else {
|
||||
$https = false;
|
||||
}
|
||||
|
||||
if (
|
||||
$https
|
||||
|| strtolower($getHeaderFromArray('x-forwarded-proto', $headers, '')) === 'https'
|
||||
) {
|
||||
$scheme = 'https';
|
||||
}
|
||||
$uri = $uri->withScheme($scheme);
|
||||
|
||||
// Set the host
|
||||
[$host, $port] = $marshalHostAndPort($headers, $server);
|
||||
if (! empty($host)) {
|
||||
$uri = $uri->withHost($host);
|
||||
if (! empty($port)) {
|
||||
$uri = $uri->withPort($port);
|
||||
}
|
||||
}
|
||||
|
||||
// URI path
|
||||
$path = $marshalRequestPath($server);
|
||||
|
||||
// Strip query string
|
||||
$path = explode('?', $path, 2)[0];
|
||||
|
||||
// URI query
|
||||
$query = '';
|
||||
if (isset($server['QUERY_STRING'])) {
|
||||
$query = ltrim($server['QUERY_STRING'], '?');
|
||||
}
|
||||
|
||||
// URI fragment
|
||||
$fragment = '';
|
||||
if (str_contains($path, '#')) {
|
||||
$parts = explode('#', $path, 2);
|
||||
assert(count($parts) >= 2);
|
||||
[$path, $fragment] = $parts;
|
||||
}
|
||||
|
||||
return $uri
|
||||
->withPath($path)
|
||||
->withFragment($fragment)
|
||||
->withQuery($query);
|
||||
}
|
||||
16
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_server.legacy.php
vendored
Normal file
16
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_server.legacy.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\normalizeServer as laminas_normalizeServer;
|
||||
|
||||
/**
|
||||
* @deprecated Use Laminas\Diactoros\normalizeServer instead
|
||||
*/
|
||||
function normalizeServer(array $server, ?callable $apacheRequestHeaderCallback = null): array
|
||||
{
|
||||
return laminas_normalizeServer(...func_get_args());
|
||||
}
|
||||
48
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_server.php
vendored
Normal file
48
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_server.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use function is_callable;
|
||||
|
||||
/**
|
||||
* Marshal the $_SERVER array
|
||||
*
|
||||
* Pre-processes and returns the $_SERVER superglobal. In particularly, it
|
||||
* attempts to detect the Authorization header, which is often not aggregated
|
||||
* correctly under various SAPI/httpd combinations.
|
||||
*
|
||||
* @param null|callable $apacheRequestHeaderCallback Callback that can be used to
|
||||
* retrieve Apache request headers. This defaults to
|
||||
* `apache_request_headers` under the Apache mod_php.
|
||||
* @return array Either $server verbatim, or with an added HTTP_AUTHORIZATION header.
|
||||
*/
|
||||
function normalizeServer(array $server, ?callable $apacheRequestHeaderCallback = null): array
|
||||
{
|
||||
if (null === $apacheRequestHeaderCallback && is_callable('apache_request_headers')) {
|
||||
$apacheRequestHeaderCallback = 'apache_request_headers';
|
||||
}
|
||||
|
||||
// If the HTTP_AUTHORIZATION value is already set, or the callback is not
|
||||
// callable, we return verbatim
|
||||
if (
|
||||
isset($server['HTTP_AUTHORIZATION'])
|
||||
|| ! is_callable($apacheRequestHeaderCallback)
|
||||
) {
|
||||
return $server;
|
||||
}
|
||||
|
||||
$apacheRequestHeaders = $apacheRequestHeaderCallback();
|
||||
if (isset($apacheRequestHeaders['Authorization'])) {
|
||||
$server['HTTP_AUTHORIZATION'] = $apacheRequestHeaders['Authorization'];
|
||||
return $server;
|
||||
}
|
||||
|
||||
if (isset($apacheRequestHeaders['authorization'])) {
|
||||
$server['HTTP_AUTHORIZATION'] = $apacheRequestHeaders['authorization'];
|
||||
return $server;
|
||||
}
|
||||
|
||||
return $server;
|
||||
}
|
||||
16
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.legacy.php
vendored
Normal file
16
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.legacy.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\normalizeUploadedFiles as laminas_normalizeUploadedFiles;
|
||||
|
||||
/**
|
||||
* @deprecated Use Laminas\Diactoros\normalizeUploadedFiles instead
|
||||
*/
|
||||
function normalizeUploadedFiles(array $files): array
|
||||
{
|
||||
return laminas_normalizeUploadedFiles(...func_get_args());
|
||||
}
|
||||
126
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.php
vendored
Normal file
126
libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.php
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
|
||||
use function is_array;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Normalize uploaded files
|
||||
*
|
||||
* Transforms each value into an UploadedFile instance, and ensures that nested
|
||||
* arrays are normalized.
|
||||
*
|
||||
* @return UploadedFileInterface[]
|
||||
* @throws Exception\InvalidArgumentException For unrecognized values.
|
||||
*/
|
||||
function normalizeUploadedFiles(array $files): array
|
||||
{
|
||||
/**
|
||||
* Traverse a nested tree of uploaded file specifications.
|
||||
*
|
||||
* @param string[]|array[] $tmpNameTree
|
||||
* @param int[]|array[] $sizeTree
|
||||
* @param int[]|array[] $errorTree
|
||||
* @param string[]|array[]|null $nameTree
|
||||
* @param string[]|array[]|null $typeTree
|
||||
* @return UploadedFile[]|array[]
|
||||
*/
|
||||
$recursiveNormalize = static function (
|
||||
array $tmpNameTree,
|
||||
array $sizeTree,
|
||||
array $errorTree,
|
||||
?array $nameTree = null,
|
||||
?array $typeTree = null
|
||||
) use (&$recursiveNormalize): array {
|
||||
$normalized = [];
|
||||
foreach ($tmpNameTree as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
// Traverse
|
||||
$normalized[$key] = $recursiveNormalize(
|
||||
$tmpNameTree[$key],
|
||||
$sizeTree[$key],
|
||||
$errorTree[$key],
|
||||
$nameTree[$key] ?? null,
|
||||
$typeTree[$key] ?? null
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$normalized[$key] = createUploadedFile([
|
||||
'tmp_name' => $tmpNameTree[$key],
|
||||
'size' => $sizeTree[$key],
|
||||
'error' => $errorTree[$key],
|
||||
'name' => $nameTree[$key] ?? null,
|
||||
'type' => $typeTree[$key] ?? null,
|
||||
]);
|
||||
}
|
||||
return $normalized;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize an array of file specifications.
|
||||
*
|
||||
* Loops through all nested files (as determined by receiving an array to the
|
||||
* `tmp_name` key of a `$_FILES` specification) and returns a normalized array
|
||||
* of UploadedFile instances.
|
||||
*
|
||||
* This function normalizes a `$_FILES` array representing a nested set of
|
||||
* uploaded files as produced by the php-fpm SAPI, CGI SAPI, or mod_php
|
||||
* SAPI.
|
||||
*
|
||||
* @param array $files
|
||||
* @return UploadedFile[]
|
||||
*/
|
||||
$normalizeUploadedFileSpecification = static function (array $files = []) use (&$recursiveNormalize): array {
|
||||
if (
|
||||
! isset($files['tmp_name']) || ! is_array($files['tmp_name'])
|
||||
|| ! isset($files['size']) || ! is_array($files['size'])
|
||||
|| ! isset($files['error']) || ! is_array($files['error'])
|
||||
) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'$files provided to %s MUST contain each of the keys "tmp_name",'
|
||||
. ' "size", and "error", with each represented as an array;'
|
||||
. ' one or more were missing or non-array values',
|
||||
__FUNCTION__
|
||||
));
|
||||
}
|
||||
|
||||
return $recursiveNormalize(
|
||||
$files['tmp_name'],
|
||||
$files['size'],
|
||||
$files['error'],
|
||||
$files['name'] ?? null,
|
||||
$files['type'] ?? null
|
||||
);
|
||||
};
|
||||
|
||||
$normalized = [];
|
||||
foreach ($files as $key => $value) {
|
||||
if ($value instanceof UploadedFileInterface) {
|
||||
$normalized[$key] = $value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value) && isset($value['tmp_name']) && is_array($value['tmp_name'])) {
|
||||
$normalized[$key] = $normalizeUploadedFileSpecification($value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value) && isset($value['tmp_name'])) {
|
||||
$normalized[$key] = createUploadedFile($value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$normalized[$key] = normalizeUploadedFiles($value);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new Exception\InvalidArgumentException('Invalid value in files specification');
|
||||
}
|
||||
return $normalized;
|
||||
}
|
||||
19
libraries/vendor/laminas/laminas-diactoros/src/functions/parse_cookie_header.legacy.php
vendored
Normal file
19
libraries/vendor/laminas/laminas-diactoros/src/functions/parse_cookie_header.legacy.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Zend\Diactoros;
|
||||
|
||||
use function func_get_args;
|
||||
use function Laminas\Diactoros\parseCookieHeader as laminas_parseCookieHeader;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see \Laminas\Diactoros\parseCookieHeader} instead
|
||||
*
|
||||
* @param string $cookieHeader A string cookie header value.
|
||||
* @return array<non-empty-string, string> key/value cookie pairs.
|
||||
*/
|
||||
function parseCookieHeader($cookieHeader): array
|
||||
{
|
||||
return laminas_parseCookieHeader(...func_get_args());
|
||||
}
|
||||
40
libraries/vendor/laminas/laminas-diactoros/src/functions/parse_cookie_header.php
vendored
Normal file
40
libraries/vendor/laminas/laminas-diactoros/src/functions/parse_cookie_header.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Laminas\Diactoros;
|
||||
|
||||
use function preg_match_all;
|
||||
use function urldecode;
|
||||
|
||||
use const PREG_SET_ORDER;
|
||||
|
||||
/**
|
||||
* Parse a cookie header according to RFC 6265.
|
||||
*
|
||||
* PHP will replace special characters in cookie names, which results in other cookies not being available due to
|
||||
* overwriting. Thus, the server request should take the cookies from the request header instead.
|
||||
*
|
||||
* @param string $cookieHeader A string cookie header value.
|
||||
* @return array<non-empty-string, string> key/value cookie pairs.
|
||||
*/
|
||||
function parseCookieHeader($cookieHeader): array
|
||||
{
|
||||
preg_match_all('(
|
||||
(?:^\\n?[ \t]*|;[ ])
|
||||
(?P<name>[!#$%&\'*+-.0-9A-Z^_`a-z|~]+)
|
||||
=
|
||||
(?P<DQUOTE>"?)
|
||||
(?P<value>[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*)
|
||||
(?P=DQUOTE)
|
||||
(?=\\n?[ \t]*$|;[ ])
|
||||
)x', $cookieHeader, $matches, PREG_SET_ORDER);
|
||||
|
||||
$cookies = [];
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$cookies[$match['name']] = urldecode($match['value']);
|
||||
}
|
||||
|
||||
return $cookies;
|
||||
}
|
||||
Reference in New Issue
Block a user