One Hat Cyber Team
Your IP:
216.73.216.30
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
proc
/
self
/
cwd
/
View File Name :
message.tar
src/CookieUtil.php 0000644 00000002606 15111172534 0010117 0 ustar 00 <?php namespace Http\Message; use Http\Message\Exception\UnexpectedValueException; final class CookieUtil { /** * Handles dates as defined by RFC 2616 section 3.3.1, and also some other * non-standard, but common formats. * * @var array */ private static $dateFormats = [ 'D, d M y H:i:s T', 'D, d M Y H:i:s T', 'D, d-M-y H:i:s T', 'D, d-M-Y H:i:s T', 'D, d-m-y H:i:s T', 'D, d-m-Y H:i:s T', 'D M j G:i:s Y', 'D M d H:i:s Y T', ]; /** * @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/BrowserKit/Cookie.php * * @param string $dateValue * * @return \DateTime * * @throws UnexpectedValueException if we cannot parse the cookie date string */ public static function parseDate($dateValue) { foreach (self::$dateFormats as $dateFormat) { if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) { return $date; } } // attempt a fallback for unusual formatting if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) { return $date; } throw new UnexpectedValueException(sprintf( 'Unparseable cookie date string "%s"', $dateValue )); } } src/Authentication.php 0000644 00000001256 15111172534 0011027 0 ustar 00 <?php namespace Http\Message; use Psr\Http\Message\RequestInterface; /** * Add authentication information to a PSR-7 Request. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ interface Authentication { /** * Alter the request to add the authentication credentials. * * To do that, the implementation might use pre-stored credentials or do * separate HTTP requests to obtain a valid token. * * @param RequestInterface $request The request without authentication information * * @return RequestInterface The request with added authentication information */ public function authenticate(RequestInterface $request); } src/CookieJar.php 0000644 00000010572 15111172535 0007720 0 ustar 00 <?php namespace Http\Message; /** * Cookie Jar holds a set of Cookies. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class CookieJar implements \Countable, \IteratorAggregate { /** * @var \SplObjectStorage<Cookie, mixed> */ private $cookies; public function __construct() { $this->cookies = new \SplObjectStorage(); } /** * Checks if there is a cookie. * * @return bool */ public function hasCookie(Cookie $cookie) { return $this->cookies->contains($cookie); } /** * Adds a cookie. */ public function addCookie(Cookie $cookie) { if (!$this->hasCookie($cookie)) { $cookies = $this->getMatchingCookies($cookie); foreach ($cookies as $matchingCookie) { if ($cookie->getValue() !== $matchingCookie->getValue() || $cookie->getMaxAge() > $matchingCookie->getMaxAge()) { $this->removeCookie($matchingCookie); continue; } } if ($cookie->hasValue()) { $this->cookies->attach($cookie); } } } /** * Removes a cookie. */ public function removeCookie(Cookie $cookie) { $this->cookies->detach($cookie); } /** * Returns the cookies. * * @return Cookie[] */ public function getCookies() { $match = function ($matchCookie) { return true; }; return $this->findMatchingCookies($match); } /** * Returns all matching cookies. * * @return Cookie[] */ public function getMatchingCookies(Cookie $cookie) { $match = function ($matchCookie) use ($cookie) { return $matchCookie->match($cookie); }; return $this->findMatchingCookies($match); } /** * Finds matching cookies based on a callable. * * @return Cookie[] */ private function findMatchingCookies(callable $match) { $cookies = []; foreach ($this->cookies as $cookie) { if ($match($cookie)) { $cookies[] = $cookie; } } return $cookies; } /** * Checks if there are cookies. * * @return bool */ public function hasCookies() { return $this->cookies->count() > 0; } /** * Sets the cookies and removes any previous one. * * @param Cookie[] $cookies */ public function setCookies(array $cookies) { $this->clear(); $this->addCookies($cookies); } /** * Adds some cookies. * * @param Cookie[] $cookies */ public function addCookies(array $cookies) { foreach ($cookies as $cookie) { $this->addCookie($cookie); } } /** * Removes some cookies. * * @param Cookie[] $cookies */ public function removeCookies(array $cookies) { foreach ($cookies as $cookie) { $this->removeCookie($cookie); } } /** * Removes cookies which match the given parameters. * * Null means that parameter should not be matched * * @param string|null $name * @param string|null $domain * @param string|null $path */ public function removeMatchingCookies($name = null, $domain = null, $path = null) { $match = function ($cookie) use ($name, $domain, $path) { $match = true; if (isset($name)) { $match = $match && ($cookie->getName() === $name); } if (isset($domain)) { $match = $match && $cookie->matchDomain($domain); } if (isset($path)) { $match = $match && $cookie->matchPath($path); } return $match; }; $cookies = $this->findMatchingCookies($match); $this->removeCookies($cookies); } /** * Removes all cookies. */ public function clear() { $this->cookies = new \SplObjectStorage(); } /** * {@inheritdoc} */ #[\ReturnTypeWillChange] public function count() { return $this->cookies->count(); } /** * {@inheritdoc} */ #[\ReturnTypeWillChange] public function getIterator() { return clone $this->cookies; } } src/filters.php 0000644 00000000262 15111172535 0007515 0 ustar 00 <?php // Register chunk filter if not found if (!array_key_exists('chunk', stream_get_filters())) { stream_filter_register('chunk', 'Http\Message\Encoding\Filter\Chunk'); } src/Exception.php 0000644 00000000204 15111172535 0007777 0 ustar 00 <?php namespace Http\Message; /** * An interface implemented by all HTTP message related exceptions. */ interface Exception { } src/Encoding/Filter/Chunk.php 0000644 00000001340 15111172535 0012066 0 ustar 00 <?php namespace Http\Message\Encoding\Filter; /** * Userland implementation of the chunk stream filter. * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class Chunk extends \php_user_filter { public function filter($in, $out, &$consumed, $closing): int { while ($bucket = stream_bucket_make_writeable($in)) { $lenbucket = stream_bucket_new($this->stream, dechex($bucket->datalen)."\r\n"); stream_bucket_append($out, $lenbucket); $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); $lenbucket = stream_bucket_new($this->stream, "\r\n"); stream_bucket_append($out, $lenbucket); } return PSFS_PASS_ON; } } src/Encoding/ChunkStream.php 0000644 00000001006 15111172535 0012014 0 ustar 00 <?php namespace Http\Message\Encoding; /** * Transform a regular stream into a chunked one. * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class ChunkStream extends FilteredStream { protected function readFilter(): string { return 'chunk'; } protected function writeFilter(): string { return 'dechunk'; } protected function fill(): void { parent::fill(); if ($this->stream->eof()) { $this->buffer .= "0\r\n\r\n"; } } } src/Encoding/DeflateStream.php 0000644 00000001501 15111172535 0012310 0 ustar 00 <?php namespace Http\Message\Encoding; use Clue\StreamFilter as Filter; use Psr\Http\Message\StreamInterface; /** * Stream deflate (RFC 1951). * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class DeflateStream extends FilteredStream { /** * @param int $level */ public function __construct(StreamInterface $stream, $level = -1) { parent::__construct($stream, ['window' => -15, 'level' => $level]); // @deprecated will be removed in 2.0 $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => -15]); } /** * {@inheritdoc} */ protected function readFilter(): string { return 'zlib.deflate'; } /** * {@inheritdoc} */ protected function writeFilter(): string { return 'zlib.inflate'; } } src/Encoding/GzipDecodeStream.php 0000644 00000001756 15111172535 0012775 0 ustar 00 <?php namespace Http\Message\Encoding; use Clue\StreamFilter as Filter; use Psr\Http\Message\StreamInterface; /** * Stream for decoding from gzip format (RFC 1952). * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class GzipDecodeStream extends FilteredStream { /** * @param int $level */ public function __construct(StreamInterface $stream, $level = -1) { if (!extension_loaded('zlib')) { throw new \RuntimeException('The zlib extension must be enabled to use this stream'); } parent::__construct($stream, ['window' => 31]); // @deprecated will be removed in 2.0 $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 31, 'level' => $level]); } /** * {@inheritdoc} */ protected function readFilter(): string { return 'zlib.inflate'; } /** * {@inheritdoc} */ protected function writeFilter(): string { return 'zlib.deflate'; } } src/Encoding/InflateStream.php 0000644 00000001615 15111172535 0012334 0 ustar 00 <?php namespace Http\Message\Encoding; use Clue\StreamFilter as Filter; use Psr\Http\Message\StreamInterface; /** * Stream inflate (RFC 1951). * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class InflateStream extends FilteredStream { /** * @param int $level */ public function __construct(StreamInterface $stream, $level = -1) { if (!extension_loaded('zlib')) { throw new \RuntimeException('The zlib extension must be enabled to use this stream'); } parent::__construct($stream, ['window' => -15]); // @deprecated will be removed in 2.0 $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => -15, 'level' => $level]); } protected function readFilter(): string { return 'zlib.inflate'; } protected function writeFilter(): string { return 'zlib.deflate'; } } src/Encoding/FilteredStream.php 0000644 00000013126 15111172536 0012511 0 ustar 00 <?php namespace Http\Message\Encoding; use Clue\StreamFilter as Filter; use Http\Message\Decorator\StreamDecorator; use Psr\Http\Message\StreamInterface; /** * A filtered stream has a filter for filtering output and a filter for filtering input made to a underlying stream. * * @author Joel Wurtz <joel.wurtz@gmail.com> */ abstract class FilteredStream implements StreamInterface { use StreamDecorator { rewind as private doRewind; seek as private doSeek; } public const BUFFER_SIZE = 8192; /** * @var callable */ protected $readFilterCallback; /** * @var resource * * @deprecated since version 1.5, will be removed in 2.0 */ protected $readFilter; /** * @var callable * * @deprecated since version 1.5, will be removed in 2.0 */ protected $writeFilterCallback; /** * @var resource * * @deprecated since version 1.5, will be removed in 2.0 */ protected $writeFilter; /** * Internal buffer. * * @var string */ protected $buffer = ''; /** * @param mixed|null $readFilterOptions * @param mixed|null $writeFilterOptions deprecated since 1.5, will be removed in 2.0 */ public function __construct(StreamInterface $stream, $readFilterOptions = null, $writeFilterOptions = null) { if (null !== $readFilterOptions) { $this->readFilterCallback = Filter\fun($this->readFilter(), $readFilterOptions); } else { $this->readFilterCallback = Filter\fun($this->readFilter()); } if (null !== $writeFilterOptions) { $this->writeFilterCallback = Filter\fun($this->writeFilter(), $writeFilterOptions); @trigger_error('The $writeFilterOptions argument is deprecated since version 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); } else { $this->writeFilterCallback = Filter\fun($this->writeFilter()); } $this->stream = $stream; } public function read(int $length): string { if (strlen($this->buffer) >= $length) { $read = substr($this->buffer, 0, $length); $this->buffer = substr($this->buffer, $length); return $read; } if ($this->stream->eof()) { $buffer = $this->buffer; $this->buffer = ''; return $buffer; } $read = $this->buffer; $this->buffer = ''; $this->fill(); return $read.$this->read($length - strlen($read)); } public function eof(): bool { return $this->stream->eof() && '' === $this->buffer; } /** * Buffer is filled by reading underlying stream. * * Callback is reading once more even if the stream is ended. * This allow to get last data in the PHP buffer otherwise this * bug is present : https://bugs.php.net/bug.php?id=48725 */ protected function fill(): void { $readFilterCallback = $this->readFilterCallback; $this->buffer .= $readFilterCallback($this->stream->read(self::BUFFER_SIZE)); if ($this->stream->eof()) { $this->buffer .= $readFilterCallback(); } } /** * {@inheritdoc} */ public function getContents(): string { $buffer = ''; while (!$this->eof()) { $buf = $this->read(self::BUFFER_SIZE); // Using a loose equality here to match on '' and false. if (null == $buf) { break; } $buffer .= $buf; } return $buffer; } /** * Always returns null because we can't tell the size of a stream when we filter. */ public function getSize(): ?int { return null; } public function __toString(): string { return $this->getContents(); } /** * Filtered streams are not seekable. * * We would need to buffer and process everything to allow seeking. */ public function isSeekable(): bool { return false; } /** * Filtered streams are not seekable and can thus not be rewound. */ public function rewind(): void { @trigger_error('Filtered streams are not seekable. This method will start raising an exception in the next major version', E_USER_DEPRECATED); $this->doRewind(); } /** * Filtered streams are not seekable. */ public function seek(int $offset, int $whence = SEEK_SET): void { @trigger_error('Filtered streams are not seekable. This method will start raising an exception in the next major version', E_USER_DEPRECATED); $this->doSeek($offset, $whence); } /** * Returns the read filter name. * * @deprecated since version 1.5, will be removed in 2.0 */ public function getReadFilter(): string { @trigger_error('The '.__CLASS__.'::'.__METHOD__.' method is deprecated since version 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); return $this->readFilter(); } /** * Returns the write filter name. */ abstract protected function readFilter(): string; /** * Returns the write filter name. * * @deprecated since version 1.5, will be removed in 2.0 */ public function getWriteFilter(): string { @trigger_error('The '.__CLASS__.'::'.__METHOD__.' method is deprecated since version 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); return $this->writeFilter(); } /** * Returns the write filter name. */ abstract protected function writeFilter(): string; } src/Encoding/DecompressStream.php 0000644 00000001621 15111172536 0013054 0 ustar 00 <?php namespace Http\Message\Encoding; use Clue\StreamFilter as Filter; use Psr\Http\Message\StreamInterface; /** * Stream decompress (RFC 1950). * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class DecompressStream extends FilteredStream { /** * @param int $level */ public function __construct(StreamInterface $stream, $level = -1) { if (!extension_loaded('zlib')) { throw new \RuntimeException('The zlib extension must be enabled to use this stream'); } parent::__construct($stream, ['window' => 15]); // @deprecated will be removed in 2.0 $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 15, 'level' => $level]); } protected function readFilter(): string { return 'zlib.inflate'; } protected function writeFilter(): string { return 'zlib.deflate'; } } src/Encoding/GzipEncodeStream.php 0000644 00000001754 15111172536 0013006 0 ustar 00 <?php namespace Http\Message\Encoding; use Clue\StreamFilter as Filter; use Psr\Http\Message\StreamInterface; /** * Stream for encoding to gzip format (RFC 1952). * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class GzipEncodeStream extends FilteredStream { /** * @param int $level */ public function __construct(StreamInterface $stream, $level = -1) { if (!extension_loaded('zlib')) { throw new \RuntimeException('The zlib extension must be enabled to use this stream'); } parent::__construct($stream, ['window' => 31, 'level' => $level]); // @deprecated will be removed in 2.0 $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 31]); } /** * {@inheritdoc} */ protected function readFilter(): string { return 'zlib.deflate'; } /** * {@inheritdoc} */ protected function writeFilter(): string { return 'zlib.inflate'; } } src/Encoding/CompressStream.php 0000644 00000001615 15111172536 0012546 0 ustar 00 <?php namespace Http\Message\Encoding; use Clue\StreamFilter as Filter; use Psr\Http\Message\StreamInterface; /** * Stream compress (RFC 1950). * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class CompressStream extends FilteredStream { /** * @param int $level */ public function __construct(StreamInterface $stream, $level = -1) { if (!extension_loaded('zlib')) { throw new \RuntimeException('The zlib extension must be enabled to use this stream'); } parent::__construct($stream, ['window' => 15, 'level' => $level]); // @deprecated will be removed in 2.0 $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 15]); } protected function readFilter(): string { return 'zlib.deflate'; } protected function writeFilter(): string { return 'zlib.inflate'; } } src/Encoding/DechunkStream.php 0000644 00000000602 15111172536 0012327 0 ustar 00 <?php namespace Http\Message\Encoding; /** * Decorate a stream which is chunked. * * Allow to decode a chunked stream * * @author Joel Wurtz <joel.wurtz@gmail.com> */ class DechunkStream extends FilteredStream { protected function readFilter(): string { return 'dechunk'; } protected function writeFilter(): string { return 'chunk'; } } src/Exception/UnexpectedValueException.php 0000644 00000000247 15111172536 0014767 0 ustar 00 <?php namespace Http\Message\Exception; use Http\Message\Exception; final class UnexpectedValueException extends \UnexpectedValueException implements Exception { } src/Decorator/RequestDecorator.php 0000644 00000002661 15111172536 0013270 0 ustar 00 <?php namespace Http\Message\Decorator; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; /** * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ trait RequestDecorator { use MessageDecorator { getMessage as getRequest; } /** * Exchanges the underlying request with another. */ public function withRequest(RequestInterface $request): RequestInterface { $new = clone $this; $new->message = $request; return $new; } public function getRequestTarget(): string { return $this->message->getRequestTarget(); } public function withRequestTarget(string $requestTarget): RequestInterface { $new = clone $this; $new->message = $this->message->withRequestTarget($requestTarget); return $new; } public function getMethod(): string { return $this->message->getMethod(); } public function withMethod(string $method): RequestInterface { $new = clone $this; $new->message = $this->message->withMethod($method); return $new; } public function getUri(): UriInterface { return $this->message->getUri(); } public function withUri(UriInterface $uri, bool $preserveHost = false): RequestInterface { $new = clone $this; $new->message = $this->message->withUri($uri, $preserveHost); return $new; } } src/Decorator/ResponseDecorator.php 0000644 00000001642 15111172536 0013434 0 ustar 00 <?php namespace Http\Message\Decorator; use Psr\Http\Message\ResponseInterface; /** * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ trait ResponseDecorator { use MessageDecorator { getMessage as getResponse; } /** * Exchanges the underlying response with another. */ public function withResponse(ResponseInterface $response): ResponseInterface { $new = clone $this; $new->message = $response; return $new; } public function getStatusCode(): int { return $this->message->getStatusCode(); } public function withStatus(int $code, string $reasonPhrase = ''): ResponseInterface { $new = clone $this; $new->message = $this->message->withStatus($code, $reasonPhrase); return $new; } public function getReasonPhrase(): string { return $this->message->getReasonPhrase(); } } src/Decorator/MessageDecorator.php 0000644 00000004315 15111172536 0013222 0 ustar 00 <?php namespace Http\Message\Decorator; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\StreamInterface; /** * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ trait MessageDecorator { /** * @var MessageInterface */ private $message; /** * Returns the decorated message. * * Since the underlying Message is immutable as well * exposing it is not an issue, because it's state cannot be altered */ public function getMessage(): MessageInterface { return $this->message; } public function getProtocolVersion(): string { return $this->message->getProtocolVersion(); } public function withProtocolVersion(string $version): MessageInterface { $new = clone $this; $new->message = $this->message->withProtocolVersion($version); return $new; } public function getHeaders(): array { return $this->message->getHeaders(); } public function hasHeader(string $header): bool { return $this->message->hasHeader($header); } public function getHeader(string $header): array { return $this->message->getHeader($header); } public function getHeaderLine(string $header): string { return $this->message->getHeaderLine($header); } public function withHeader(string $header, $value): MessageInterface { $new = clone $this; $new->message = $this->message->withHeader($header, $value); return $new; } public function withAddedHeader(string $header, $value): MessageInterface { $new = clone $this; $new->message = $this->message->withAddedHeader($header, $value); return $new; } public function withoutHeader(string $header): MessageInterface { $new = clone $this; $new->message = $this->message->withoutHeader($header); return $new; } public function getBody(): StreamInterface { return $this->message->getBody(); } public function withBody(StreamInterface $body): MessageInterface { $new = clone $this; $new->message = $this->message->withBody($body); return $new; } } src/Decorator/StreamDecorator.php 0000644 00000003244 15111172537 0013072 0 ustar 00 <?php namespace Http\Message\Decorator; use Psr\Http\Message\StreamInterface; /** * Decorates a stream. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ trait StreamDecorator { /** * @var StreamInterface */ protected $stream; public function __toString(): string { return $this->stream->__toString(); } public function close(): void { $this->stream->close(); } public function detach() { return $this->stream->detach(); } public function getSize(): ?int { return $this->stream->getSize(); } public function tell(): int { return $this->stream->tell(); } public function eof(): bool { return $this->stream->eof(); } public function isSeekable(): bool { return $this->stream->isSeekable(); } public function seek(int $offset, int $whence = SEEK_SET): void { $this->stream->seek($offset, $whence); } public function rewind(): void { $this->stream->rewind(); } public function isWritable(): bool { return $this->stream->isWritable(); } public function write(string $string): int { return $this->stream->write($string); } public function isReadable(): bool { return $this->stream->isReadable(); } public function read(int $length): string { return $this->stream->read($length); } public function getContents(): string { return $this->stream->getContents(); } public function getMetadata(string $key = null) { return $this->stream->getMetadata($key); } } src/RequestMatcher.php 0000644 00000001241 15111172537 0011001 0 ustar 00 <?php namespace Http\Message; use Psr\Http\Message\RequestInterface; /** * Match a request. * * PSR-7 equivalent of Symfony's RequestMatcher * * @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/RequestMatcherInterface.php * * @author Joel Wurtz <joel.wurtz@gmail.com> */ interface RequestMatcher { /** * Decides whether the rule(s) implemented by the strategy matches the supplied request. * * @param RequestInterface $request The PSR7 request to check for a match * * @return bool true if the request matches, false otherwise */ public function matches(RequestInterface $request); } src/Cookie.php 0000644 00000025757 15111172537 0007300 0 ustar 00 <?php namespace Http\Message; /** * Cookie Value Object. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> * * @see http://tools.ietf.org/search/rfc6265 */ final class Cookie { /** * @var string */ private $name; /** * @var string|null */ private $value; /** * @var int|null */ private $maxAge; /** * @var string|null */ private $domain; /** * @var string */ private $path; /** * @var bool */ private $secure; /** * @var bool */ private $httpOnly; /** * Expires attribute is HTTP 1.0 only and should be avoided. * * @var \DateTime|null */ private $expires; /** * @param string $name * @param string|null $value * @param int|null $maxAge * @param string|null $domain * @param string|null $path * @param bool $secure * @param bool $httpOnly * @param \DateTime|null $expires Expires attribute is HTTP 1.0 only and should be avoided. * * @throws \InvalidArgumentException if name, value or max age is not valid */ public function __construct( $name, $value = null, $maxAge = null, $domain = null, $path = null, $secure = false, $httpOnly = false, \DateTime $expires = null ) { $this->validateName($name); $this->validateValue($value); $this->validateMaxAge($maxAge); $this->name = $name; $this->value = $value; $this->maxAge = $maxAge; $this->expires = $expires; $this->domain = $this->normalizeDomain($domain); $this->path = $this->normalizePath($path); $this->secure = (bool) $secure; $this->httpOnly = (bool) $httpOnly; } /** * Creates a new cookie without any attribute validation. * * @param string $name * @param string|null $value * @param int $maxAge * @param string|null $domain * @param string|null $path * @param bool $secure * @param bool $httpOnly * @param \DateTime|null $expires Expires attribute is HTTP 1.0 only and should be avoided. */ public static function createWithoutValidation( $name, $value = null, $maxAge = null, $domain = null, $path = null, $secure = false, $httpOnly = false, \DateTime $expires = null ) { $cookie = new self('name', null, null, $domain, $path, $secure, $httpOnly, $expires); $cookie->name = $name; $cookie->value = $value; $cookie->maxAge = $maxAge; return $cookie; } /** * Returns the name. * * @return string */ public function getName() { return $this->name; } /** * Returns the value. * * @return string|null */ public function getValue() { return $this->value; } /** * Checks if there is a value. * * @return bool */ public function hasValue() { return isset($this->value); } /** * Sets the value. * * @param string|null $value * * @return Cookie */ public function withValue($value) { $this->validateValue($value); $new = clone $this; $new->value = $value; return $new; } /** * Returns the max age. * * @return int|null */ public function getMaxAge() { return $this->maxAge; } /** * Checks if there is a max age. * * @return bool */ public function hasMaxAge() { return isset($this->maxAge); } /** * Sets the max age. * * @param int|null $maxAge * * @return Cookie */ public function withMaxAge($maxAge) { $this->validateMaxAge($maxAge); $new = clone $this; $new->maxAge = $maxAge; return $new; } /** * Returns the expiration time. * * @return \DateTime|null */ public function getExpires() { return $this->expires; } /** * Checks if there is an expiration time. * * @return bool */ public function hasExpires() { return isset($this->expires); } /** * Sets the expires. * * @return Cookie */ public function withExpires(\DateTime $expires = null) { $new = clone $this; $new->expires = $expires; return $new; } /** * Checks if the cookie is expired. * * @return bool */ public function isExpired() { return isset($this->expires) and $this->expires < new \DateTime(); } /** * Returns the domain. * * @return string|null */ public function getDomain() { return $this->domain; } /** * Checks if there is a domain. * * @return bool */ public function hasDomain() { return isset($this->domain); } /** * Sets the domain. * * @param string|null $domain * * @return Cookie */ public function withDomain($domain) { $new = clone $this; $new->domain = $this->normalizeDomain($domain); return $new; } /** * Checks whether this cookie is meant for this domain. * * @see http://tools.ietf.org/html/rfc6265#section-5.1.3 * * @param string $domain * * @return bool */ public function matchDomain($domain) { // Domain is not set or exact match if (!$this->hasDomain() || 0 === strcasecmp($domain, $this->domain)) { return true; } // Domain is not an IP address if (filter_var($domain, FILTER_VALIDATE_IP)) { return false; } return (bool) preg_match(sprintf('/\b%s$/i', preg_quote($this->domain)), $domain); } /** * Returns the path. * * @return string */ public function getPath() { return $this->path; } /** * Sets the path. * * @param string|null $path * * @return Cookie */ public function withPath($path) { $new = clone $this; $new->path = $this->normalizePath($path); return $new; } /** * Checks whether this cookie is meant for this path. * * @see http://tools.ietf.org/html/rfc6265#section-5.1.4 * * @param string $path * * @return bool */ public function matchPath($path) { return $this->path === $path || (0 === strpos($path, rtrim($this->path, '/').'/')); } /** * Checks whether this cookie may only be sent over HTTPS. * * @return bool */ public function isSecure() { return $this->secure; } /** * Sets whether this cookie should only be sent over HTTPS. * * @param bool $secure * * @return Cookie */ public function withSecure($secure) { $new = clone $this; $new->secure = (bool) $secure; return $new; } /** * Check whether this cookie may not be accessed through Javascript. * * @return bool */ public function isHttpOnly() { return $this->httpOnly; } /** * Sets whether this cookie may not be accessed through Javascript. * * @param bool $httpOnly * * @return Cookie */ public function withHttpOnly($httpOnly) { $new = clone $this; $new->httpOnly = (bool) $httpOnly; return $new; } /** * Checks if this cookie represents the same cookie as $cookie. * * This does not compare the values, only name, domain and path. * * @return bool */ public function match(self $cookie) { return $this->name === $cookie->name && $this->domain === $cookie->domain and $this->path === $cookie->path; } /** * Validates cookie attributes. * * @return bool */ public function isValid() { try { $this->validateName($this->name); $this->validateValue($this->value); $this->validateMaxAge($this->maxAge); } catch (\InvalidArgumentException $e) { return false; } return true; } /** * Validates the name attribute. * * @see http://tools.ietf.org/search/rfc2616#section-2.2 * * @param string $name * * @throws \InvalidArgumentException if the name is empty or contains invalid characters */ private function validateName($name) { if (strlen($name) < 1) { throw new \InvalidArgumentException('The name cannot be empty'); } // Name attribute is a token as per spec in RFC 2616 if (preg_match('/[\x00-\x20\x22\x28-\x29\x2C\x2F\x3A-\x40\x5B-\x5D\x7B\x7D\x7F]/', $name)) { throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); } } /** * Validates a value. * * @see http://tools.ietf.org/html/rfc6265#section-4.1.1 * * @param string|null $value * * @throws \InvalidArgumentException if the value contains invalid characters */ private function validateValue($value) { if (isset($value)) { if (preg_match('/[^\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]/', $value)) { throw new \InvalidArgumentException(sprintf('The cookie value "%s" contains invalid characters.', $value)); } } } /** * Validates a Max-Age attribute. * * @param int|null $maxAge * * @throws \InvalidArgumentException if the Max-Age is not an empty or integer value */ private function validateMaxAge($maxAge) { if (isset($maxAge)) { if (!is_int($maxAge)) { throw new \InvalidArgumentException('Max-Age must be integer'); } } } /** * Remove the leading '.' and lowercase the domain as per spec in RFC 6265. * * @see http://tools.ietf.org/html/rfc6265#section-4.1.2.3 * @see http://tools.ietf.org/html/rfc6265#section-5.1.3 * @see http://tools.ietf.org/html/rfc6265#section-5.2.3 * * @param string|null $domain * * @return string */ private function normalizeDomain($domain) { if (isset($domain)) { $domain = ltrim(strtolower($domain), '.'); } return $domain; } /** * Processes path as per spec in RFC 6265. * * @see http://tools.ietf.org/html/rfc6265#section-5.1.4 * @see http://tools.ietf.org/html/rfc6265#section-5.2.4 * * @param string|null $path * * @return string */ private function normalizePath($path) { $path = rtrim($path, '/'); if (empty($path) or '/' !== substr($path, 0, 1)) { $path = '/'; } return $path; } } src/Formatter/SimpleFormatter.php 0000644 00000002313 15111172537 0013126 0 ustar 00 <?php namespace Http\Message\Formatter; use Http\Message\Formatter; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Normalize a request or a response into a string or an array. * * @author Joel Wurtz <joel.wurtz@gmail.com> * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ class SimpleFormatter implements Formatter { /** * {@inheritdoc} */ public function formatRequest(RequestInterface $request) { return sprintf( '%s %s %s', $request->getMethod(), $request->getUri()->__toString(), $request->getProtocolVersion() ); } /** * {@inheritdoc} */ public function formatResponse(ResponseInterface $response) { return sprintf( '%s %s %s', $response->getStatusCode(), $response->getReasonPhrase(), $response->getProtocolVersion() ); } /** * Formats a response in context of its request. * * @return string */ public function formatResponseForRequest(ResponseInterface $response, RequestInterface $request) { return $this->formatResponse($response); } } src/Formatter/CurlCommandFormatter.php 0000644 00000006032 15111172537 0014103 0 ustar 00 <?php namespace Http\Message\Formatter; use Http\Message\Formatter; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * A formatter that prints a cURL command for HTTP requests. * * @author Tobias Nyholm <tobias.nyholm@gmail.com> */ class CurlCommandFormatter implements Formatter { /** * {@inheritdoc} */ public function formatRequest(RequestInterface $request) { $command = sprintf('curl %s', escapeshellarg((string) $request->getUri()->withFragment(''))); if ('1.0' === $request->getProtocolVersion()) { $command .= ' --http1.0'; } elseif ('2.0' === $request->getProtocolVersion()) { $command .= ' --http2'; } $method = strtoupper($request->getMethod()); if ('HEAD' === $method) { $command .= ' --head'; } elseif ('GET' !== $method) { $command .= ' --request '.$method; } $command .= $this->getHeadersAsCommandOptions($request); $body = $request->getBody(); if ($body->getSize() > 0) { // escapeshellarg argument max length on Windows, but longer body in curl command would be impractical anyways if ($body->getSize() > 8192) { $data = '[too long stream omitted]'; } elseif ($body->isSeekable()) { $data = $body->__toString(); $body->rewind(); // all non-printable ASCII characters and <DEL> except for \t, \r, \n if (preg_match('/([\x00-\x09\x0C\x0E-\x1F\x7F])/', $data)) { $data = '[binary stream omitted]'; } } else { $data = '[non-seekable stream omitted]'; } $escapedData = @escapeshellarg($data); if (empty($escapedData)) { $escapedData = 'We couldn\'t not escape the data properly'; } $command .= sprintf(' --data %s', $escapedData); } return $command; } /** * {@inheritdoc} */ public function formatResponse(ResponseInterface $response) { return ''; } /** * Formats a response in context of its request. * * @return string */ public function formatResponseForRequest(ResponseInterface $response, RequestInterface $request) { return $this->formatResponse($response); } /** * @return string */ private function getHeadersAsCommandOptions(RequestInterface $request) { $command = ''; foreach ($request->getHeaders() as $name => $values) { if ('host' === strtolower($name) && $values[0] === $request->getUri()->getHost()) { continue; } if ('user-agent' === strtolower($name)) { $command .= sprintf(' -A %s', escapeshellarg($values[0])); continue; } $command .= sprintf(' -H %s', escapeshellarg($name.': '.$request->getHeaderLine($name))); } return $command; } } src/Formatter/FullHttpMessageFormatter.php 0000644 00000005676 15111172537 0014763 0 ustar 00 <?php namespace Http\Message\Formatter; use Http\Message\Formatter; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * A formatter that prints the complete HTTP message. * * @author Tobias Nyholm <tobias.nyholm@gmail.com> */ class FullHttpMessageFormatter implements Formatter { /** * The maximum length of the body. * * @var int|null */ private $maxBodyLength; /** * @var string */ private $binaryDetectionRegex; /** * @param int|null $maxBodyLength * @param string $binaryDetectionRegex By default, this is all non-printable ASCII characters and <DEL> except for \t, \r, \n */ public function __construct($maxBodyLength = 1000, string $binaryDetectionRegex = '/([\x00-\x09\x0C\x0E-\x1F\x7F])/') { $this->maxBodyLength = $maxBodyLength; $this->binaryDetectionRegex = $binaryDetectionRegex; } /** * {@inheritdoc} */ public function formatRequest(RequestInterface $request) { $message = sprintf( "%s %s HTTP/%s\n", $request->getMethod(), $request->getRequestTarget(), $request->getProtocolVersion() ); foreach ($request->getHeaders() as $name => $values) { $message .= $name.': '.implode(', ', $values)."\n"; } return $this->addBody($request, $message); } /** * {@inheritdoc} */ public function formatResponse(ResponseInterface $response) { $message = sprintf( "HTTP/%s %s %s\n", $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase() ); foreach ($response->getHeaders() as $name => $values) { $message .= $name.': '.implode(', ', $values)."\n"; } return $this->addBody($response, $message); } /** * Formats a response in context of its request. * * @return string */ public function formatResponseForRequest(ResponseInterface $response, RequestInterface $request) { return $this->formatResponse($response); } /** * Add the message body if the stream is seekable. * * @param string $message * * @return string */ private function addBody(MessageInterface $request, $message) { $message .= "\n"; $stream = $request->getBody(); if (!$stream->isSeekable() || 0 === $this->maxBodyLength) { // Do not read the stream return $message; } $data = $stream->__toString(); $stream->rewind(); if (preg_match($this->binaryDetectionRegex, $data)) { return $message.'[binary stream omitted]'; } if (null === $this->maxBodyLength) { return $message.$data; } return $message.mb_substr($data, 0, $this->maxBodyLength); } } src/Authentication/AutoBasicAuth.php 0000644 00000002213 15111172537 0013520 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; /** * Authenticate a PSR-7 Request using Basic Auth based on credentials in the URI. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class AutoBasicAuth implements Authentication { /** * Whether user info should be removed from the URI. * * @var bool */ private $shouldRemoveUserInfo; /** * @param bool|true $shouldRremoveUserInfo */ public function __construct($shouldRremoveUserInfo = true) { $this->shouldRemoveUserInfo = (bool) $shouldRremoveUserInfo; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { $uri = $request->getUri(); $userInfo = $uri->getUserInfo(); if (!empty($userInfo)) { if ($this->shouldRemoveUserInfo) { $request = $request->withUri($uri->withUserInfo('')); } $request = $request->withHeader('Authorization', sprintf('Basic %s', base64_encode($userInfo))); } return $request; } } src/Authentication/Matching.php 0000644 00000003453 15111172540 0012557 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Http\Message\RequestMatcher\CallbackRequestMatcher; use Psr\Http\Message\RequestInterface; @trigger_error('The '.__NAMESPACE__.'\Matching class is deprecated since version 1.2 and will be removed in 2.0. Use Http\Message\Authentication\RequestConditional instead.', E_USER_DEPRECATED); /** * Authenticate a PSR-7 Request if the request is matching. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> * * @deprecated since since version 1.2, and will be removed in 2.0. Use {@link RequestConditional} instead. */ final class Matching implements Authentication { /** * @var Authentication */ private $authentication; /** * @var CallbackRequestMatcher */ private $matcher; public function __construct(Authentication $authentication, callable $matcher = null) { if (is_null($matcher)) { $matcher = function () { return true; }; } $this->authentication = $authentication; $this->matcher = new CallbackRequestMatcher($matcher); } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { if ($this->matcher->matches($request)) { return $this->authentication->authenticate($request); } return $request; } /** * Creates a matching authentication for an URL. * * @param string $url * * @return self */ public static function createUrlMatcher(Authentication $authentication, $url) { $matcher = function (RequestInterface $request) use ($url) { return preg_match($url, $request->getRequestTarget()); }; return new static($authentication, $matcher); } } src/Authentication/Bearer.php 0000644 00000001267 15111172540 0012226 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; /** * Authenticate a PSR-7 Request using a token. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class Bearer implements Authentication { /** * @var string */ private $token; /** * @param string $token */ public function __construct($token) { $this->token = $token; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { $header = sprintf('Bearer %s', $this->token); return $request->withHeader('Authorization', $header); } } src/Authentication/Wsse.php 0000644 00000003333 15111172540 0011743 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; /** * Authenticate a PSR-7 Request using WSSE. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class Wsse implements Authentication { /** * @var string */ private $username; /** * @var string */ private $password; /** * @var string */ private $hashAlgorithm; /** * @param string $username * @param string $password * @param string $hashAlgorithm To use a better hashing algorithm than the weak sha1, pass the algorithm to use, e.g. "sha512" */ public function __construct($username, $password, $hashAlgorithm = 'sha1') { $this->username = $username; $this->password = $password; if (false === in_array($hashAlgorithm, hash_algos())) { throw new \InvalidArgumentException(sprintf('Unaccepted hashing algorithm: %s', $hashAlgorithm)); } $this->hashAlgorithm = $hashAlgorithm; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { $nonce = substr(md5(uniqid(uniqid().'_', true)), 0, 16); $created = date('c'); $digest = base64_encode(hash($this->hashAlgorithm, base64_decode($nonce).$created.$this->password, true)); $wsse = sprintf( 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"', $this->username, $digest, $nonce, $created ); return $request ->withHeader('Authorization', 'WSSE profile="UsernameToken"') ->withHeader('X-WSSE', $wsse) ; } } src/Authentication/RequestConditional.php 0000644 00000001734 15111172540 0014641 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Http\Message\RequestMatcher; use Psr\Http\Message\RequestInterface; /** * Authenticate a PSR-7 Request if the request is matching the given request matcher. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class RequestConditional implements Authentication { /** * @var RequestMatcher */ private $requestMatcher; /** * @var Authentication */ private $authentication; public function __construct(RequestMatcher $requestMatcher, Authentication $authentication) { $this->requestMatcher = $requestMatcher; $this->authentication = $authentication; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { if ($this->requestMatcher->matches($request)) { return $this->authentication->authenticate($request); } return $request; } } src/Authentication/Header.php 0000644 00000001174 15111172540 0012213 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; class Header implements Authentication { /** * @var string */ private $name; /** * @var string|string[] */ private $value; /** * @param string|string[] $value */ public function __construct(string $name, $value) { $this->name = $name; $this->value = $value; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { return $request->withHeader($this->name, $this->value); } } src/Authentication/Chain.php 0000644 00000002252 15111172540 0012043 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; /** * Authenticate a PSR-7 Request with a multiple authentication methods. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class Chain implements Authentication { /** * @var Authentication[] */ private $authenticationChain = []; /** * @param Authentication[] $authenticationChain */ public function __construct(array $authenticationChain = []) { foreach ($authenticationChain as $authentication) { if (!$authentication instanceof Authentication) { throw new \InvalidArgumentException( 'Members of the authentication chain must be of type Http\Message\Authentication' ); } } $this->authenticationChain = $authenticationChain; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { foreach ($this->authenticationChain as $authentication) { $request = $authentication->authenticate($request); } return $request; } } src/Authentication/QueryParam.php 0000644 00000002116 15111172541 0013107 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; /** * Authenticate a PSR-7 Request by adding parameters to its query. * * Note: Although in some cases it can be useful, we do not recommend using query parameters for authentication. * Credentials in the URL is generally unsafe as they are not encrypted, anyone can see them. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class QueryParam implements Authentication { /** * @var array */ private $params = []; public function __construct(array $params) { $this->params = $params; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { $uri = $request->getUri(); $query = $uri->getQuery(); $params = []; parse_str($query, $params); $params = array_merge($params, $this->params); $query = http_build_query($params, '', '&'); $uri = $uri->withQuery($query); return $request->withUri($uri); } } src/Authentication/BasicAuth.php 0000644 00000001612 15111172541 0012664 0 ustar 00 <?php namespace Http\Message\Authentication; use Http\Message\Authentication; use Psr\Http\Message\RequestInterface; /** * Authenticate a PSR-7 Request using Basic Auth. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class BasicAuth implements Authentication { /** * @var string */ private $username; /** * @var string */ private $password; /** * @param string $username * @param string $password */ public function __construct($username, $password) { $this->username = $username; $this->password = $password; } /** * {@inheritdoc} */ public function authenticate(RequestInterface $request) { $header = sprintf('Basic %s', base64_encode(sprintf('%s:%s', $this->username, $this->password))); return $request->withHeader('Authorization', $header); } } src/RequestMatcher/RequestMatcher.php 0000644 00000004070 15111172541 0013733 0 ustar 00 <?php namespace Http\Message\RequestMatcher; use Http\Message\RequestMatcher as RequestMatcherInterface; use Psr\Http\Message\RequestInterface; /** * A port of the Symfony RequestMatcher for PSR-7. * * @author Fabien Potencier <fabien@symfony.com> * @author Joel Wurtz <joel.wurtz@gmail.com> */ final class RequestMatcher implements RequestMatcherInterface { /** * @var string */ private $path; /** * @var string */ private $host; /** * @var array */ private $methods = []; /** * @var string[] */ private $schemes = []; /** * The regular expressions used for path or host must be specified without delimiter. * You do not need to escape the forward slash / to match it. * * @param string|null $path Regular expression for the path * @param string|null $host Regular expression for the hostname * @param string|string[]|null $methods Method or list of methods to match * @param string|string[]|null $schemes Scheme or list of schemes to match (e.g. http or https) */ public function __construct($path = null, $host = null, $methods = [], $schemes = []) { $this->path = $path; $this->host = $host; $this->methods = array_map('strtoupper', (array) $methods); $this->schemes = array_map('strtolower', (array) $schemes); } /** * {@inheritdoc} * * @api */ public function matches(RequestInterface $request) { if ($this->schemes && !in_array($request->getUri()->getScheme(), $this->schemes)) { return false; } if ($this->methods && !in_array($request->getMethod(), $this->methods)) { return false; } if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getUri()->getPath()))) { return false; } if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getUri()->getHost())) { return false; } return true; } } src/RequestMatcher/RegexRequestMatcher.php 0000644 00000001724 15111172541 0014731 0 ustar 00 <?php namespace Http\Message\RequestMatcher; use Http\Message\RequestMatcher; use Psr\Http\Message\RequestInterface; @trigger_error('The '.__NAMESPACE__.'\RegexRequestMatcher class is deprecated since version 1.2 and will be removed in 2.0. Use Http\Message\RequestMatcher\RequestMatcher instead.', E_USER_DEPRECATED); /** * Match a request with a regex on the uri. * * @author Joel Wurtz <joel.wurtz@gmail.com> * * @deprecated since version 1.2 and will be removed in 2.0. Use {@link RequestMatcher} instead. */ final class RegexRequestMatcher implements RequestMatcher { /** * Matching regex. * * @var string */ private $regex; /** * @param string $regex */ public function __construct($regex) { $this->regex = $regex; } /** * {@inheritdoc} */ public function matches(RequestInterface $request) { return (bool) preg_match($this->regex, (string) $request->getUri()); } } src/RequestMatcher/CallbackRequestMatcher.php 0000644 00000001155 15111172541 0015351 0 ustar 00 <?php namespace Http\Message\RequestMatcher; use Http\Message\RequestMatcher; use Psr\Http\Message\RequestInterface; /** * Match a request with a callback. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> */ final class CallbackRequestMatcher implements RequestMatcher { /** * @var callable */ private $callback; public function __construct(callable $callback) { $this->callback = $callback; } /** * {@inheritdoc} */ public function matches(RequestInterface $request) { return (bool) call_user_func($this->callback, $request); } } src/StreamFactory/GuzzleStreamFactory.php 0000644 00000001772 15111172541 0014620 0 ustar 00 <?php namespace Http\Message\StreamFactory; use GuzzleHttp\Psr7\Utils; use Http\Message\StreamFactory; if (!interface_exists(StreamFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\GuzzleStreamFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Guzzle streams. * * @author Михаил Красильников <m.krasilnikov@yandex.ru> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Guzzle PSR-17 factory */ final class GuzzleStreamFactory implements StreamFactory { /** * {@inheritdoc} */ public function createStream($body = null) { if (class_exists(Utils::class)) { return Utils::streamFor($body); } // legacy support for guzzle/psr7 1.* return \GuzzleHttp\Psr7\stream_for($body); } } src/StreamFactory/DiactorosStreamFactory.php 0000644 00000003017 15111172542 0015262 0 ustar 00 <?php namespace Http\Message\StreamFactory; use Http\Message\StreamFactory; use Laminas\Diactoros\Stream as LaminasStream; use Psr\Http\Message\StreamInterface; use Zend\Diactoros\Stream as ZendStream; if (!interface_exists(StreamFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\DiactorosStreamFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Diactoros streams. * * @author Михаил Красильников <m.krasilnikov@yandex.ru> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Diactoros PSR-17 factory */ final class DiactorosStreamFactory implements StreamFactory { /** * {@inheritdoc} */ public function createStream($body = null) { if ($body instanceof StreamInterface) { return $body; } if (is_resource($body)) { if (class_exists(LaminasStream::class)) { return new LaminasStream($body); } return new ZendStream($body); } if (class_exists(LaminasStream::class)) { $stream = new LaminasStream('php://memory', 'rw'); } else { $stream = new ZendStream('php://memory', 'rw'); } if (null !== $body && '' !== $body) { $stream->write((string) $body); } return $stream; } } src/StreamFactory/SlimStreamFactory.php 0000644 00000002270 15111172542 0014237 0 ustar 00 <?php namespace Http\Message\StreamFactory; use Http\Message\StreamFactory; use Psr\Http\Message\StreamInterface; use Slim\Http\Stream; if (!interface_exists(StreamFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\SlimStreamFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Slim 3 streams. * * @author Mika Tuupola <tuupola@appelsiini.net> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Slim PSR-17 factory */ final class SlimStreamFactory implements StreamFactory { /** * {@inheritdoc} */ public function createStream($body = null) { if ($body instanceof StreamInterface) { return $body; } if (is_resource($body)) { return new Stream($body); } $resource = fopen('php://memory', 'r+'); $stream = new Stream($resource); if (null !== $body && '' !== $body) { $stream->write((string) $body); } return $stream; } } src/Stream/BufferedStream.php 0000644 00000014046 15111172542 0012201 0 ustar 00 <?php namespace Http\Message\Stream; use Psr\Http\Message\StreamInterface; /** * Decorator to make any stream seekable. * * Internally it buffers an existing StreamInterface into a php://temp resource (or memory). By default it will use * 2 megabytes of memory before writing to a temporary disk file. * * Due to this, very large stream can suffer performance issue (i/o slowdown). */ class BufferedStream implements StreamInterface { /** @var resource The buffered resource used to seek previous data */ private $resource; /** @var int|null size of the stream if available */ private $size; /** @var StreamInterface The underlying stream decorated by this class */ private $stream; /** @var int How many bytes were written */ private $written = 0; /** * @param StreamInterface $stream Decorated stream * @param bool $useFileBuffer Whether to use a file buffer (write to a file, if data exceed a certain size) * by default, set this to false to only use memory * @param int $memoryBuffer In conjunction with using file buffer, limit (in bytes) from which it begins to buffer * the data in a file */ public function __construct(StreamInterface $stream, $useFileBuffer = true, $memoryBuffer = 2097152) { $this->stream = $stream; $this->size = $stream->getSize(); if ($useFileBuffer) { $this->resource = fopen('php://temp/maxmemory:'.$memoryBuffer, 'rw+'); } else { $this->resource = fopen('php://memory', 'rw+'); } if (false === $this->resource) { throw new \RuntimeException('Cannot create a resource over temp or memory implementation'); } } public function __toString(): string { try { $this->rewind(); return $this->getContents(); } catch (\Throwable $throwable) { return ''; } } public function close(): void { if (null === $this->resource) { throw new \RuntimeException('Cannot close on a detached stream'); } $this->stream->close(); fclose($this->resource); } public function detach() { if (null === $this->resource) { return null; } // Force reading the remaining data of the stream $this->getContents(); $resource = $this->resource; $this->stream->close(); $this->stream = null; $this->resource = null; return $resource; } public function getSize(): ?int { if (null === $this->resource) { return null; } if (null === $this->size && $this->stream->eof()) { return $this->written; } return $this->size; } public function tell(): int { if (null === $this->resource) { throw new \RuntimeException('Cannot tell on a detached stream'); } $tell = ftell($this->resource); if (false === $tell) { throw new \RuntimeException('ftell failed'); } return $tell; } public function eof(): bool { if (null === $this->resource) { throw new \RuntimeException('Cannot call eof on a detached stream'); } // We are at the end only when both our resource and underlying stream are at eof return $this->stream->eof() && (ftell($this->resource) === $this->written); } public function isSeekable(): bool { return null !== $this->resource; } public function seek(int $offset, int $whence = SEEK_SET): void { if (null === $this->resource) { throw new \RuntimeException('Cannot seek on a detached stream'); } fseek($this->resource, $offset, $whence); } public function rewind(): void { if (null === $this->resource) { throw new \RuntimeException('Cannot rewind on a detached stream'); } rewind($this->resource); } public function isWritable(): bool { return false; } public function write(string $string): int { throw new \RuntimeException('Cannot write on this stream'); } public function isReadable(): bool { return null !== $this->resource; } public function read(int $length): string { if (null === $this->resource) { throw new \RuntimeException('Cannot read on a detached stream'); } if ($length < 0) { throw new \InvalidArgumentException('Can not read a negative amount of bytes'); } $read = ''; // First read from the resource if (ftell($this->resource) !== $this->written) { $read = fread($this->resource, $length); } if (false === $read) { throw new \RuntimeException('Failed to read from resource'); } $bytesRead = strlen($read); if ($bytesRead < $length) { $streamRead = $this->stream->read($length - $bytesRead); // Write on the underlying stream what we read $this->written += fwrite($this->resource, $streamRead); $read .= $streamRead; } return $read; } public function getContents(): string { if (null === $this->resource) { throw new \RuntimeException('Cannot read on a detached stream'); } $read = ''; while (!$this->eof()) { $read .= $this->read(8192); } return $read; } public function getMetadata(?string $key = null) { if (null === $this->resource) { if (null === $key) { return []; } return null; } $metadata = stream_get_meta_data($this->resource); if (null === $key) { return $metadata; } if (!array_key_exists($key, $metadata)) { return null; } return $metadata[$key]; } } src/Builder/ResponseBuilder.php 0000644 00000007461 15111172542 0012546 0 ustar 00 <?php namespace Http\Message\Builder; use Psr\Http\Message\ResponseInterface; /** * Fills response object with values. */ class ResponseBuilder { /** * The response to be built. * * @var ResponseInterface */ protected $response; /** * Create builder for the given response. */ public function __construct(ResponseInterface $response) { $this->response = $response; } /** * Return response. * * @return ResponseInterface */ public function getResponse() { return $this->response; } /** * Add headers represented by an array of header lines. * * @param string[] $headers response headers as array of header lines * * @return $this * * @throws \UnexpectedValueException for invalid header values * @throws \InvalidArgumentException for invalid status code arguments */ public function setHeadersFromArray(array $headers) { $status = array_shift($headers); $this->setStatus($status); foreach ($headers as $headerLine) { $headerLine = trim($headerLine); if ('' === $headerLine) { continue; } $this->addHeader($headerLine); } return $this; } /** * Add headers represented by a single string. * * @param string $headers response headers as single string * * @return $this * * @throws \InvalidArgumentException if $headers is not a string on object with __toString() * @throws \UnexpectedValueException for invalid header values */ public function setHeadersFromString($headers) { if (!(is_string($headers) || (is_object($headers) && method_exists($headers, '__toString'))) ) { throw new \InvalidArgumentException( sprintf( '%s expects parameter 1 to be a string, %s given', __METHOD__, is_object($headers) ? get_class($headers) : gettype($headers) ) ); } $this->setHeadersFromArray(explode("\r\n", $headers)); return $this; } /** * Set response status from a status string. * * @param string $statusLine response status as a string * * @return $this * * @throws \InvalidArgumentException for invalid status line */ public function setStatus($statusLine) { $parts = explode(' ', $statusLine, 3); if (count($parts) < 2 || 0 !== strpos(strtolower($parts[0]), 'http/')) { throw new \InvalidArgumentException( sprintf('"%s" is not a valid HTTP status line', $statusLine) ); } $reasonPhrase = count($parts) > 2 ? $parts[2] : ''; $this->response = $this->response ->withStatus((int) $parts[1], $reasonPhrase) ->withProtocolVersion(substr($parts[0], 5)); return $this; } /** * Add header represented by a string. * * @param string $headerLine response header as a string * * @return $this * * @throws \InvalidArgumentException for invalid header names or values */ public function addHeader($headerLine) { $parts = explode(':', $headerLine, 2); if (2 !== count($parts)) { throw new \InvalidArgumentException( sprintf('"%s" is not a valid HTTP header line', $headerLine) ); } $name = trim($parts[0]); $value = trim($parts[1]); if ($this->response->hasHeader($name)) { $this->response = $this->response->withAddedHeader($name, $value); } else { $this->response = $this->response->withHeader($name, $value); } return $this; } } src/MessageFactory/GuzzleMessageFactory.php 0000644 00000002721 15111172542 0015076 0 ustar 00 <?php namespace Http\Message\MessageFactory; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; use Http\Message\MessageFactory; if (!interface_exists(MessageFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\GuzzleMessageFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Guzzle messages. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Guzzle PSR-17 factory */ final class GuzzleMessageFactory implements MessageFactory { /** * {@inheritdoc} */ public function createRequest( $method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1' ) { return new Request( $method, $uri, $headers, $body, $protocolVersion ); } /** * {@inheritdoc} */ public function createResponse( $statusCode = 200, $reasonPhrase = null, array $headers = [], $body = null, $protocolVersion = '1.1' ) { return new Response( $statusCode, $headers, $body, $protocolVersion, $reasonPhrase ); } } src/MessageFactory/SlimMessageFactory.php 0000644 00000004000 15111172542 0014512 0 ustar 00 <?php namespace Http\Message\MessageFactory; use Http\Message\MessageFactory; use Http\Message\StreamFactory\SlimStreamFactory; use Http\Message\UriFactory\SlimUriFactory; use Slim\Http\Headers; use Slim\Http\Request; use Slim\Http\Response; if (!interface_exists(MessageFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\SlimMessageFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Slim 3 messages. * * @author Mika Tuupola <tuupola@appelsiini.net> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Slim PSR-17 factory */ final class SlimMessageFactory implements MessageFactory { /** * @var SlimStreamFactory */ private $streamFactory; /** * @var SlimUriFactory */ private $uriFactory; public function __construct() { $this->streamFactory = new SlimStreamFactory(); $this->uriFactory = new SlimUriFactory(); } /** * {@inheritdoc} */ public function createRequest( $method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1' ) { return (new Request( $method, $this->uriFactory->createUri($uri), new Headers($headers), [], [], $this->streamFactory->createStream($body), [] ))->withProtocolVersion($protocolVersion); } /** * {@inheritdoc} */ public function createResponse( $statusCode = 200, $reasonPhrase = null, array $headers = [], $body = null, $protocolVersion = '1.1' ) { return (new Response( $statusCode, new Headers($headers), $this->streamFactory->createStream($body) ))->withProtocolVersion($protocolVersion); } } src/MessageFactory/DiactorosMessageFactory.php 0000644 00000004673 15111172542 0015555 0 ustar 00 <?php namespace Http\Message\MessageFactory; use Http\Message\MessageFactory; use Http\Message\StreamFactory\DiactorosStreamFactory; use Laminas\Diactoros\Request as LaminasRequest; use Laminas\Diactoros\Response as LaminasResponse; use Zend\Diactoros\Request as ZendRequest; use Zend\Diactoros\Response as ZendResponse; if (!interface_exists(MessageFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\DiactorosMessageFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Diactoros messages. * * @author GeLo <geloen.eric@gmail.com> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Diactoros PSR-17 factory */ final class DiactorosMessageFactory implements MessageFactory { /** * @var DiactorosStreamFactory */ private $streamFactory; public function __construct() { $this->streamFactory = new DiactorosStreamFactory(); } /** * {@inheritdoc} */ public function createRequest( $method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1' ) { if (class_exists(LaminasRequest::class)) { return (new LaminasRequest( $uri, $method, $this->streamFactory->createStream($body), $headers ))->withProtocolVersion($protocolVersion); } return (new ZendRequest( $uri, $method, $this->streamFactory->createStream($body), $headers ))->withProtocolVersion($protocolVersion); } /** * {@inheritdoc} */ public function createResponse( $statusCode = 200, $reasonPhrase = null, array $headers = [], $body = null, $protocolVersion = '1.1' ) { if (class_exists(LaminasResponse::class)) { return (new LaminasResponse( $this->streamFactory->createStream($body), $statusCode, $headers ))->withProtocolVersion($protocolVersion); } return (new ZendResponse( $this->streamFactory->createStream($body), $statusCode, $headers ))->withProtocolVersion($protocolVersion); } } src/Formatter.php 0000644 00000001764 15111172542 0010016 0 ustar 00 <?php namespace Http\Message; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Formats a request and/or a response as a string. * * @author Márk Sági-Kazár <mark.sagikazar@gmail.com> * * The formatResponseForRequest method will be added to this interface in the next major version, replacing the formatRequest method. * Meanwhile, callers SHOULD check the formatter for the existence of formatResponseForRequest and call that if available. * * @method string formatResponseForRequest(ResponseInterface $response, RequestInterface $request) Formats a response in context of its request. */ interface Formatter { /** * Formats a request. * * @return string */ public function formatRequest(RequestInterface $request); /** * @deprecated since 1.13, use formatResponseForRequest() instead * * Formats a response. * * @return string */ public function formatResponse(ResponseInterface $response); } src/UriFactory/GuzzleUriFactory.php 0000644 00000001632 15111172542 0013424 0 ustar 00 <?php namespace Http\Message\UriFactory; use GuzzleHttp\Psr7\Utils; use Http\Message\UriFactory; use function GuzzleHttp\Psr7\uri_for; if (!interface_exists(UriFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\GuzzleUriFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Guzzle URI. * * @author David de Boer <david@ddeboer.nl> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Guzzle PSR-17 factory */ final class GuzzleUriFactory implements UriFactory { /** * {@inheritdoc} */ public function createUri($uri) { if (class_exists(Utils::class)) { return Utils::uriFor($uri); } return uri_for($uri); } } src/UriFactory/SlimUriFactory.php 0000644 00000002021 15111172542 0013041 0 ustar 00 <?php namespace Http\Message\UriFactory; use Http\Message\UriFactory; use Psr\Http\Message\UriInterface; use Slim\Http\Uri; if (!interface_exists(UriFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\SlimUriFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Slim 3 URI. * * @author Mika Tuupola <tuupola@appelsiini.net> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Slim PSR-17 factory */ final class SlimUriFactory implements UriFactory { /** * {@inheritdoc} */ public function createUri($uri) { if ($uri instanceof UriInterface) { return $uri; } if (is_string($uri)) { return Uri::createFromString($uri); } throw new \InvalidArgumentException('URI must be a string or UriInterface'); } } src/UriFactory/DiactorosUriFactory.php 0000644 00000002267 15111172542 0014100 0 ustar 00 <?php namespace Http\Message\UriFactory; use Http\Message\UriFactory; use Laminas\Diactoros\Uri as LaminasUri; use Psr\Http\Message\UriInterface; use Zend\Diactoros\Uri as ZendUri; if (!interface_exists(UriFactory::class)) { throw new \LogicException('You cannot use "Http\Message\MessageFactory\DiactorosUriFactory" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory". Note that this package is deprecated, use "psr/http-factory" instead'); } /** * Creates Diactoros URI. * * @author David de Boer <david@ddeboer.nl> * * @deprecated This will be removed in php-http/message2.0. Consider using the official Diactoros PSR-17 factory */ final class DiactorosUriFactory implements UriFactory { /** * {@inheritdoc} */ public function createUri($uri) { if ($uri instanceof UriInterface) { return $uri; } elseif (is_string($uri)) { if (class_exists(LaminasUri::class)) { return new LaminasUri($uri); } return new ZendUri($uri); } throw new \InvalidArgumentException('URI must be a string or UriInterface'); } } .php-cs-fixer.dist.php 0000644 00000000473 15111172542 0010605 0 ustar 00 <?php $finder = PhpCsFixer\Finder::create() ->in(__DIR__.'/src') ->in(__DIR__.'/spec') ->name('*.php') ; $config = new PhpCsFixer\Config(); return $config ->setRiskyAllowed(true) ->setRules([ '@Symfony' => true, 'single_line_throw' => false, ]) ->setFinder($finder) ; README.md 0000644 00000002460 15111172542 0006024 0 ustar 00 # HTTP Message [](https://github.com/php-http/message/releases) [](LICENSE) [](https://github.com/php-http/message/actions/workflows/ci.yml) [](https://packagist.org/packages/php-http/message) **HTTP Message related tools.** ## Install Via Composer ``` bash $ composer require php-http/message ``` ## Intro This package contains various PSR-7 tools which might be useful in an HTTP workflow: - Authentication method implementations - Various Stream encoding tools - Message decorators - Message factory implementations for Guzzle PSR-7 and Diactoros - Cookie implementation - Request matchers ## Documentation Please see the [official documentation](http://docs.php-http.org/en/latest/message.html). ## Testing ``` bash $ composer test ``` ## Credits Thanks to [Cuzzle](https://github.com/namshi/cuzzle) for inpiration for the `CurlCommandFormatter`. ## License The MIT License (MIT). Please see [License File](LICENSE) for more information. LICENSE 0000644 00000002072 15111172542 0005551 0 ustar 00 Copyright (c) 2015-2016 PHP HTTP Team <team@php-http.org> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. puli.json 0000644 00000011306 15111172542 0006410 0 ustar 00 { "version": "1.0", "name": "php-http/message", "bindings": { "064d003d-78a1-48c4-8f3b-1f92ff25da69": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\DiactorosMessageFactory", "type": "Http\\Message\\MessageFactory", "parameters": { "depends": "Zend\\Diactoros\\Request" } }, "0836751e-6558-4d1b-8993-4a52012947c3": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\SlimMessageFactory", "type": "Http\\Message\\ResponseFactory" }, "1d127622-dc61-4bfa-b9da-d221548d72c3": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\SlimMessageFactory", "type": "Http\\Message\\RequestFactory" }, "2438c2d0-0658-441f-8855-ddaf0f87d54d": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\GuzzleMessageFactory", "type": "Http\\Message\\MessageFactory", "parameters": { "depends": "GuzzleHttp\\Psr7\\Request" } }, "253aa08c-d705-46e7-b1d2-e28c97eef792": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\GuzzleMessageFactory", "type": "Http\\Message\\RequestFactory", "parameters": { "depends": "GuzzleHttp\\Psr7\\Request" } }, "273a34f9-62f4-4ba1-9801-b1284d49ff89": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\StreamFactory\\GuzzleStreamFactory", "type": "Http\\Message\\StreamFactory", "parameters": { "depends": "GuzzleHttp\\Psr7\\Stream" } }, "304b83db-b594-4d83-ae75-1f633adf92f7": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\UriFactory\\GuzzleUriFactory", "type": "Http\\Message\\UriFactory", "parameters": { "depends": "GuzzleHttp\\Psr7\\Uri" } }, "3f4bc1cd-aa95-4702-9fa7-65408e471691": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\UriFactory\\DiactorosUriFactory", "type": "Http\\Message\\UriFactory", "parameters": { "depends": "Zend\\Diactoros\\Uri" } }, "4672a6ee-ad9e-4109-a5d1-b7d46f26c7a1": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\SlimMessageFactory", "type": "Http\\Message\\MessageFactory" }, "6234e947-d3bd-43eb-97d5-7f9e22e6bb1b": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\DiactorosMessageFactory", "type": "Http\\Message\\ResponseFactory", "parameters": { "depends": "Zend\\Diactoros\\Response" } }, "6a9ad6ce-d82c-470f-8e30-60f21d9d95bf": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\UriFactory\\SlimUriFactory", "type": "Http\\Message\\UriFactory" }, "72c2afa0-ea56-4d03-adb6-a9f241a8a734": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\StreamFactory\\SlimStreamFactory", "type": "Http\\Message\\StreamFactory" }, "95c1be8f-39fe-4abd-8351-92cb14379a75": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\StreamFactory\\DiactorosStreamFactory", "type": "Http\\Message\\StreamFactory", "parameters": { "depends": "Zend\\Diactoros\\Stream" } }, "a018af27-7590-4dcf-83a1-497f95604cd6": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\GuzzleMessageFactory", "type": "Http\\Message\\ResponseFactory", "parameters": { "depends": "GuzzleHttp\\Psr7\\Response" } }, "c07955b1-de46-43db-923b-d07fae9382cb": { "_class": "Puli\\Discovery\\Binding\\ClassBinding", "class": "Http\\Message\\MessageFactory\\DiactorosMessageFactory", "type": "Http\\Message\\RequestFactory", "parameters": { "depends": "Zend\\Diactoros\\Request" } } } } composer.json 0000644 00000003252 15111172542 0007267 0 ustar 00 { "name": "php-http/message", "description": "HTTP Message related tools", "keywords": [ "message", "http", "psr-7" ], "homepage": "http://php-http.org", "license": "MIT", "authors": [ { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com" } ], "require": { "php": "^7.2 || ^8.0", "clue/stream-filter": "^1.5", "psr/http-message": "^1.1 || ^2.0" }, "provide": { "php-http/message-factory-implementation": "1.0" }, "require-dev": { "ext-zlib": "*", "ergebnis/composer-normalize": "^2.6", "guzzlehttp/psr7": "^1.0 || ^2.0", "php-http/message-factory": "^1.0.2", "phpspec/phpspec": "^5.1 || ^6.3 || ^7.1", "slim/slim": "^3.0", "laminas/laminas-diactoros": "^2.0 || ^3.0" }, "suggest": { "ext-zlib": "Used with compressor/decompressor streams", "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", "laminas/laminas-diactoros": "Used with Diactoros Factories", "slim/slim": "Used with Slim Framework PSR-7 implementation" }, "config": { "sort-packages": true, "allow-plugins": { "ergebnis/composer-normalize": true } }, "autoload": { "psr-4": { "Http\\Message\\": "src/" }, "files": [ "src/filters.php" ] }, "autoload-dev": { "psr-4": { "spec\\Http\\Message\\": "spec/" } }, "scripts": { "test": "vendor/bin/phpspec run", "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml" } } apigen.neon 0000644 00000000106 15111172542 0006664 0 ustar 00 source: - src/ destination: build/api/ templateTheme: bootstrap CHANGELOG.md 0000644 00000020074 15111172542 0006357 0 ustar 00 # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [1.16.0] - 2023-05-17 - Remove direct dependency on `php-http/message-factory` as it is only needed for the deprecated Httplug factories. Upgrade to PSR-17 message factories provided by your HTTP client implementation. If you need the Httplug factories for the time being, you can `composer require php-http/message-factory` in your application. ## [1.15.0] - 2023-05-10 **If you use the decorator classes, you might need to adjust your code to the parameter and return type declarations added in PSR-7** - Actually make compatible with PSR-7 1.1 and 2.0 - Drop support for PHP 7.1 ## [1.14.0] - 2023-04-14 (broken) **This release is not actually compatible with PSR-7 1.1 or 2.0** - Allow installation with http-message (PSR-7) version 2 in addition to version 1. - Support for PHP 8.2 ## [1.13.0] - 2022-02-11 - Added `Formatter::formatResponseForRequest()` to allow the formatter to get context from the request to decide what of the response to output. - Deprecated `Formatter::formatResponse()` in favor of the new `formatResponseForRequest` method. ## [1.12.0] - 2021-08-29 - Added support for adjusting binary detection regex in FullHttpMessageFormatter. ## [1.11.2] - 2021-08-03 - Support GuzzleHttp/Psr7 version 2.0 in the (deprecated) GuzzleStreamFactory. ## [1.11.1] - 2021-05-24 - Support GuzzleHttp/Psr7 version 2.0 in the (deprecated) GuzzleUriFactory. ## [1.11.0] - 2020-02-01 - Migrated from `zendframework/zend-diactoros` to `laminas/laminas-diactoros`. Users are encouraged to update their dependencies by simply replacing the Zend package with the Laminas package. Due to the [laminas-zendframework-brige](https://github.com/laminas/laminas-zendframework-bridge), BC changes are not expected and legacy code does not need to be refactored (though it is [recommended and simple](https://docs.laminas.dev/migration/)). - The diactoros factories of `php-http/message` will return objects from the `Laminas\Diactoros\` namespace, if the respective classes are available via autoloading, but continue to return objects from `Zend\Diactoros\` namespace otherwise. - Allow to specify the hashing algorithm for WSSE authentication. ## [1.10.0] - 2020-11-11 - Added support for PHP 8.0. ## [1.9.1] - 2020-10-13 - Improved detection of binary stream to not consider newlines, carriage return or tabs as binary. ## [1.9.0] - 2020-08-17 - Omitted binary body in FullHttpMessageFormatter and CurlCommandFormatter. `[binary stream omitted]` will be shown instead. ### Added - New Header authentication method for arbitrary header authentication. ## [1.8.0] - 2019-08-05 ### Changed - Raised minimum PHP version to 7.1 ### Fixed - Fatal error on `CurlCommandFormatter` when body is larger than `escapeshellarg` allowed length. - Do not read stream in message formatter if stream is not seekable. ## [1.7.2] - 2018-10-30 ### Fixed - FilteredStream uses `@trigger_error` instead of throwing exceptions to not break careless users. You still need to fix your stream code to respect `isSeekable`. Seeking does not work as expected, and we will add exceptions in version 2. ## [1.7.1] - 2018-10-29 ### Fixed - FilteredStream is not actually seekable ## [1.7.0] - 2018-08-15 ### Fixed - Fix CurlCommandFormatter for binary request payloads - Fix QueryParam authentication to assemble proper URL regardless of PHP `arg_separator.output` directive - Do not pass `null` parameters to `Clue\StreamFilter\fun` ### Changed - Dropped tests on HHVM ## [1.6.0] - 2017-07-05 ### Added - CookieUtil::parseDate to create a date from cookie date string ### Fixed - Fix curl command of CurlFormatter when there is an user-agent header ## [1.5.0] - 2017-02-14 ### Added - Check for empty string in Stream factories - Cookie::createWithoutValidation Static constructor to create a cookie. Will not perform any attribute validation during instantiation. - Cookie::isValid Method to check if cookie attributes are valid. ### Fixed - FilteredStream::getSize returns null because the contents size is unknown. - Stream factories does not rewinds streams. The previous behavior was not coherent between factories and inputs. ### Deprecated - FilteredStream::getReadFilter The read filter is internal and should never be used by consuming code. - FilteredStream::getWriteFilter We did not implement writing to the streams at all. And if we do, the filter is an internal information and should not be used by consuming code. ## [1.4.1] - 2016-12-16 ### Fixed - Cookie::matchPath Cookie with root path (`/`) will not match sub path (e.g. `/cookie`). ## [1.4.0] - 2016-10-20 ### Added - Message, stream and URI factories for [Slim Framework](https://github.com/slimphp/Slim) - BufferedStream that allow you to decorate a non-seekable stream with a seekable one. - cUrlFormatter to be able to redo the request with a cURL command ## [1.3.1] - 2016-07-15 ### Fixed - FullHttpMessageFormatter will not read from streams that you cannot rewind (non-seekable) - FullHttpMessageFormatter will not read from the stream if $maxBodyLength is zero - FullHttpMessageFormatter rewinds streams after they are read ## [1.3.0] - 2016-07-14 ### Added - FullHttpMessageFormatter to include headers and body in the formatted message ### Fixed - #41: Response builder broke header value ## [1.2.0] - 2016-03-29 ### Added - The RequestMatcher is built after the Symfony RequestMatcher and separates scheme, host and path expressions and provides an option to filter on the method - New RequestConditional authentication method using request matchers - Add automatic basic auth info detection based on the URL ### Changed - Improved ResponseBuilder ### Deprecated - RegexRequestMatcher, use RequestMatcher instead - Matching authenitcation method, use RequestConditional instead ## [1.1.0] - 2016-02-25 ### Added - Add a request matcher interface and regex implementation - Add a callback request matcher implementation - Add a ResponseBuilder, to create PSR7 Response from a string ### Fixed - Fix casting string on a FilteredStream not filtering the output ## [1.0.0] - 2016-01-27 ## [0.2.0] - 2015-12-29 ### Added - Autoregistration of stream filters using Composer autoload - Cookie - [Apigen](http://www.apigen.org/) configuration ## [0.1.2] - 2015-12-26 ### Added - Request and response factory bindings ### Fixed - Chunk filter namespace in Dechunk stream ## [0.1.1] - 2015-12-25 ### Added - Formatter ## 0.1.0 - 2015-12-24 ### Added - Authentication - Encoding - Message decorator - Message factory (Guzzle, Diactoros) [Unreleased]: https://github.com/php-http/message/compare/1.10.0...HEAD [1.10.0]: https://github.com/php-http/message/compare/1.9.1...1.10.0 [1.9.1]: https://github.com/php-http/message/compare/1.9.0...1.9.1 [1.9.0]: https://github.com/php-http/message/compare/1.8.0...1.9.0 [1.8.0]: https://github.com/php-http/message/compare/1.7.2...1.8.0 [1.7.2]: https://github.com/php-http/message/compare/v1.7.1...1.7.2 [1.7.1]: https://github.com/php-http/message/compare/1.7.0...v1.7.1 [1.7.0]: https://github.com/php-http/message/compare/1.6.0...1.7.0 [1.6.0]: https://github.com/php-http/message/compare/1.5.0...1.6.0 [1.5.0]: https://github.com/php-http/message/compare/v1.4.1...1.5.0 [1.4.1]: https://github.com/php-http/message/compare/v1.4.0...v1.4.1 [1.4.0]: https://github.com/php-http/message/compare/v1.3.1...v1.4.0 [1.3.1]: https://github.com/php-http/message/compare/v1.3.0...v1.3.1 [1.3.0]: https://github.com/php-http/message/compare/v1.2.0...v1.3.0 [1.2.0]: https://github.com/php-http/message/compare/v1.1.0...v1.2.0 [1.1.0]: https://github.com/php-http/message/compare/v1.0.0...v1.1.0 [1.0.0]: https://github.com/php-http/message/compare/0.2.0...v1.0.0 [0.2.0]: https://github.com/php-http/message/compare/v0.1.2...0.2.0 [0.1.2]: https://github.com/php-http/message/compare/v0.1.1...v0.1.2 [0.1.1]: https://github.com/php-http/message/compare/v0.1.0...v0.1.1 index.blade.php 0000644 00000010657 15111365441 0007444 0 ustar 00 @extends('layouts.user') @push('css') @endpush @section('contents') <div class="breadcrumb-area"> <h3 class="title">@lang('Support Tickets')</h3> <ul class="breadcrumb"> <li> <a href="user-dashboard.html">Dashboard</a> </li> <li> @lang('Support Tickets') </li> </ul> </div> <div class="dashboard--content-item"> <div class="d-flex justify-content-between"> <a href="{{ route('user.message.create') }}" class="ms-auto btn btn-primary mb-2"> @lang('Create Ticket') </a> </div> <div class="table-responsive table--mobile-lg"> <table class="table bg--body"> <thead> <tr> <th>{{ __('Ticket') }}</th> <th>{{ __('Subject') }}</th> <th>{{ __('Message') }}</th> <th>{{ __('Time') }}</th> <th>{{ __('Status') }}</th> <th>{{ __('Action') }}</th> </tr> </thead> <tbody> @if (count($convs) == 0) <tr> <td colspan="12"> <h4 class="text-center m-0 py-2">{{__('No Data Found')}}</h4> </td> </tr> @else @foreach($convs as $conv) <tr class="conv"> <input type="hidden" value="{{$conv->id}}"> <td data-label="{{ __('Ticket') }}"> <div> <strong>{{ $conv->ticket_number}}</strong> </div> </td> <td data-label="{{ __('Subject') }}"> <div> {{$conv->subject}} </div> </td> <td data-label="{{ __('Message') }}"> <div> {{$conv->message}} </div> </td> <td data-label="{{ __('Time') }}"> <div> {{$conv->created_at->diffForHumans()}} </div> </td> <td data-label="{{ __('Status') }}"> <div> @if($conv->status == 1) <span class="badge badge--success">@lang('open')</span> @else <span class="badge badge--danger">@lang('close')</span> @endif </div> </td> <td data-label="{{ __('Action') }}"> <div class="d-flex"> <a href="{{route('user.message.show',$conv->id)}}" class="link view me-1 btn d-block btn-sm btn-primary"><i class="fa fa-eye"></i></a> </div> </td> </tr> @endforeach @endif </tbody> </table> </div> </div> <div class="modal modal-blur fade" id="confirm-delete" tabindex="-1" role="dialog" aria-hidden="true"> <div class="modal-dialog modal-sm modal-dialog-centered" role="document"> <div class="modal-content"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <div class="modal-status bg-danger"></div> <div class="modal-body text-center py-4"> <svg xmlns="http://www.w3.org/2000/svg" class="icon mb-2 text-danger icon-lg" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 9v2m0 4v.01" /><path d="M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75" /></svg> <h3>{{__('Are you sure')}}?</h3> <div class="text-muted">{{__("You are about to delete this Ticket.")}}</div> </div> <div class="modal-footer"> <div class="w-100"> <div class="row"> <div class="col"><a href="#" class="btn w-100" data-bs-dismiss="modal"> {{__('Cancel')}} </a></div> <div class="col"> <a href="javascript:;" class="btn btn-danger w-100 btn-ok"> {{__('Delete')}} </a> </div> </div> </div> </div> </div> </div> </div> </div> @endsection @push('js') <script type="text/javascript"> 'use strict'; $('#confirm-delete').on('show.bs.modal', function(e) { $(this).find('.btn-ok').attr('href', $(e.relatedTarget).data('href')); }); </script> @endpush create.blade.php 0000644 00000005763 15111365441 0007602 0 ustar 00 @extends('layouts.user') @push('css') @endpush @section('contents') <div class="breadcrumb-area"> <h3 class="title">@lang('Support Ticket')</h3> <ul class="breadcrumb"> <li> <a href="{{ route('user.dashboard') }}">@lang('Dashboard')</a> </li> <li> @lang('Support Ticket') </li> </ul> </div> <div class="dashboard--content-item"> <div class="row g-3"> <div class="col-12"> <div class="card default--card"> <div class="card-body"> @includeIf('includes.flash') <form id="request-form" action="{{ route('user.message.store') }}" method="POST" enctype="multipart/form-data"> @csrf <div class="row gy-3 gy-md-4"> <div class="col-sm-12"> <div class="form-group"> <label class="form-label required">{{__('Subject')}}</label> <input type="text" name="subject" class="form-control @error('subject') is-invalid @enderror" autocomplete="off" placeholder="{{__('Enter Subject')}}" value="{{ old('subject') }}"> @error('subject') <p class="text-danger mt-2">{{ $message }}</p> @enderror </div> </div> <div class="col-sm-12"> <div class="form-group"> <label class="form-label">{{__('Message')}}</label> <textarea name="message" class="form-control nic-edit @error('message') is-invalid @enderror" cols="30" rows="5" placeholder="{{__('Enter Subject')}}"></textarea> @error('message') <p class="text-danger mt-2">{{ $message }}</p> @enderror </div> </div> <div class="col-sm-12"> <div class="form-group"> <input type="file" name="attachment" class="form-control @error('attachment') is-invalid @enderror"> @error('attachment') <p class="text-danger mt-2">{{ $message }}</p> @enderror </div> </div> <div class="col-sm-12"> <label class="form-label d-none d-sm-block"> </label> <button type="submit" class="cmn--btn bg--primary submit-btn w-100 border-0">{{__('Submit')}}</button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection show.blade.php 0000644 00000016063 15111365441 0007312 0 ustar 00 @extends('layouts.user') @push('css') @endpush @section('contents') <div class="breadcrumb-area"> <h3 class="title">@lang('Support Tickets')</h3> <ul class="breadcrumb"> <li> <a href="user-dashboard.html">@lang('Dashboard')</a> </li> <li> @lang('Support Tickets') </li> </ul> </div> <div class="dashboard--content-item"> <div class="row justify-content-center"> <div class="col-lg-4"> <div class="card default--card h-100"> <div class="card-body"> <div class="chatbox__list__wrapper"> <div class="d-flex justify-content-between py-4 border-bottom border--dark"> <h3> <a href="{{ route('user.message.index') }}">@lang('Tickets')<i class="fas fa-arrow-right "></i></a> </h3> </div> <ul class="chat__list nav-tab nav border-0"> <li> <a class="chat__item active" href="#0"> <div class="item__inner"> <div class="post__creator"> <div class="post__creator-thumb d-flex justify-content-between"> <span class="username">{{ $data->ticket_number }} </span> </div> <div class="post__creator-content"> <h4 class="name d-inline-block">{{ $data->subject }}</h4> </div> </div> <ul class="chat__meta d-flex justify-content-between"> <li><span class="last-msg"></span></li> <li><span class="last-chat-time">{{ $data->created_at->diffForHumans() }}</span></li> </ul> </div> </a> </li> </ul> </div> </div> </div> </div> <div class="col-lg-8"> <div class="card default--card h-100"> <div class="card-body"> <div class="tab-content"> <div class="tab-pane show fade active" id="c1"> <div class="chat__msg"> <div class="chat__msg-header py-2"> <div class="post__creator align-items-center"> <div class="post__creator-content"> <h4 class="name d-inline-block">@lang('Ticket Number') : {{ $data->ticket_number }} </h4> </div> <a class="profile-link" href="javascript:void(0)"></a> </div> </div> <div class="chat__msg-body"> <ul class="msg__wrapper mt-3"> @foreach($data->messages as $key=>$value) @if($value->user_id == 0) <li class="incoming__msg"> <div class="msg__item"> <div class="post__creator"> <div class="post__creator-content"> <p>{{ $value->message }}</p> <span class="comment-date text--secondary">{{ $value->created_at->diffForHumans() }}</span> </div> </div> </div> </li> @else <li class="outgoing__msg"> <div class="msg__item"> <div class="post__creator "> <div class="post__creator-content"> <p class="out__msg">{{ $value->message }} <br> @if ($value->photo != NULL) <a href="{{ asset('assets/images/'.$value->photo)}}" download="" class="text-white"><i class="fas fa-paperclip"></i> @lang('attachment')-{{ $key +=1 }}</a> @endif </p> <span class="comment-date text--secondary">{{ $value->created_at->diffForHumans() }}</span> </div> </div> </div> </li> @endif @endforeach </ul> </div> @if ($data->status == 1) <div class="chat__msg-footer"> <form action="{{ route('user.message.conversation',$data->id) }}" class="send__msg" method="post" enctype="multipart/form-data"> @csrf <div class="input-group"> <input id="upload-file" type="file" name="photo" class="form-control d-none"> <label class="-formlabel upload-file" for="upload-file"> <i class="fas fa-cloud-upload-alt"></i> </label> </div> <div class="input-group"> <textarea class="form-control form--control shadow-none" name="message"></textarea> <button class="border-0 outline-0 send-btn" type="submit"><i class="fab fa-telegram-plane"></i></button> </div> </form> </div> @endif </div> </div> </div> </div> </div> </div> </div> </div> @endsection @push('js') @endpush