From 23be945fd2810ee82e3a23cbcd2352c9bda43d4f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 14:44:18 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- library/vendor/iplx/Http/Client.php | 199 +++++++++++++++++++ library/vendor/iplx/Http/ClientInterface.php | 22 +++ library/vendor/iplx/Http/Handle.php | 32 +++ library/vendor/iplx/Http/MessageTrait.php | 174 ++++++++++++++++ library/vendor/iplx/Http/Request.php | 143 ++++++++++++++ library/vendor/iplx/Http/Response.php | 64 ++++++ library/vendor/iplx/Http/Stream.php | 283 +++++++++++++++++++++++++++ library/vendor/iplx/Http/Uri.php | 202 +++++++++++++++++++ 8 files changed, 1119 insertions(+) create mode 100644 library/vendor/iplx/Http/Client.php create mode 100644 library/vendor/iplx/Http/ClientInterface.php create mode 100644 library/vendor/iplx/Http/Handle.php create mode 100644 library/vendor/iplx/Http/MessageTrait.php create mode 100644 library/vendor/iplx/Http/Request.php create mode 100644 library/vendor/iplx/Http/Response.php create mode 100644 library/vendor/iplx/Http/Stream.php create mode 100644 library/vendor/iplx/Http/Uri.php (limited to 'library/vendor/iplx/Http') diff --git a/library/vendor/iplx/Http/Client.php b/library/vendor/iplx/Http/Client.php new file mode 100644 index 0000000..39d8905 --- /dev/null +++ b/library/vendor/iplx/Http/Client.php @@ -0,0 +1,199 @@ +getHeaders() as $name => $values) { + $headers[] = $name . ': ' . implode(', ', $values); + } + + $curlOptions = [ + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_FAILONERROR => true, + CURLOPT_USERAGENT => $this->getAgent() + ]; + + if (isset($options['curl'])) { + $curlOptions += $options['curl']; + } + + $curlOptions += [ + CURLOPT_CUSTOMREQUEST => $request->getMethod(), + CURLOPT_HTTPHEADER => $headers, + CURLOPT_RETURNTRANSFER => false, + CURLOPT_URL => (string) $request->getUri()->withFragment('') + ]; + + if (! $request->hasHeader('Accept')) { + $curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:'; + } + + if (! $request->hasHeader('Content-Type')) { + $curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:'; + } + + if (! $request->hasHeader('Expect')) { + $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:'; + } + + if ($request->getBody()->getSize() !== 0) { + $curlOptions[CURLOPT_UPLOAD] = true; + + $body = $request->getBody(); + if ($body->isSeekable()) { + $body->seek(0); + } + + $curlOptions[CURLOPT_READFUNCTION] = function ($ch, $infile, $length) use ($body) { + return $body->read($length); + }; + } + + if ($request->getProtocolVersion()) { + $protocolVersion = null; + switch ($request->getProtocolVersion()) { + case '2.0': + if (version_compare(phpversion(), '7.0.7', '<')) { + throw new RuntimeException('You need at least PHP 7.0.7 to use HTTP 2.0'); + } + $protocolVersion = CURL_HTTP_VERSION_2; + break; + case '1.1': + $protocolVersion = CURL_HTTP_VERSION_1_1; + break; + default: + $protocolVersion = CURL_HTTP_VERSION_1_0; + } + + $curlOptions[CURLOPT_HTTP_VERSION] = $protocolVersion; + } + + $handle = new Handle(); + + $curlOptions[CURLOPT_HEADERFUNCTION] = function($ch, $header) use ($handle) { + $size = strlen($header); + + if (! trim($header) || strpos($header, 'HTTP/') === 0) { + return $size; + } + + list($key, $value) = explode(': ', $header, 2); + $handle->responseHeaders[$key] = rtrim($value, "\r\n"); + + return $size; + }; + + $handle->responseBody = Stream::open(); + + $curlOptions[CURLOPT_WRITEFUNCTION] = function ($ch, $string) use ($handle) { + return $handle->responseBody->write($string); + }; + + $ch = ! empty($this->handles) ? array_pop($this->handles) : curl_init(); + + curl_setopt_array($ch, $curlOptions); + + $handle->handle = $ch; + + return $handle; + } + + /** + * Execute a cURL handle and return the response + * + * @param Handle $handle + * + * @return ResponseInterface + * + * @throws RuntimeException + */ + protected function executeHandle(Handle $handle) + { + $ch = $handle->handle; + + $success = curl_exec($ch); + + if ($success === false) { + throw new RuntimeException(curl_error($ch)); + } + + $response = new Response( + curl_getinfo($ch, CURLINFO_HTTP_CODE), $handle->responseHeaders, $handle->responseBody + ); + + if (count($this->handles) >= self::MAX_HANDLES) { + curl_close($ch); + } else { + curl_reset($ch); + + $this->handles[] = $ch; + } + + return $response; + } + + public function send(RequestInterface $request, array $options = []) + { + $handle = $this->createHandle($request, $options); + + $response = $this->executeHandle($handle); + + return $response; + } +} diff --git a/library/vendor/iplx/Http/ClientInterface.php b/library/vendor/iplx/Http/ClientInterface.php new file mode 100644 index 0000000..e7765a7 --- /dev/null +++ b/library/vendor/iplx/Http/ClientInterface.php @@ -0,0 +1,22 @@ +protocolVersion; + } + + public function withProtocolVersion($version) + { + $message = clone $this; + $message->protocolVersion = $version; + + return $message; + } + + public function getHeaders() + { + return array_combine($this->headerNames, $this->headerValues); + } + + public function hasHeader($header) + { + return isset($this->headerValues[strtolower($header)]); + } + + public function getHeader($header) + { + $header = strtolower($header); + + if (! isset($this->headerValues[$header])) { + return []; + } + + return $this->headerValues[$header]; + } + + public function getHeaderLine($name) + { + $name = strtolower($name); + + if (! isset($this->headerValues[$name])) { + return ''; + } + + return implode(', ', $this->headerValues[$name]); + } + + public function withHeader($name, $value) + { + $name = rtrim($name); + + $value = $this->normalizeHeaderValues($value); + + $normalized = strtolower($name); + + $message = clone $this; + $message->headerNames[$normalized] = $name; + $message->headerValues[$normalized] = $value; + + return $message; + } + + public function withAddedHeader($name, $value) + { + $name = rtrim($name); + + $value = $this->normalizeHeaderValues($value); + + $normalized = strtolower($name); + + $message = clone $this; + if (isset($message->headerNames[$normalized])) { + $message->headerValues[$normalized] = array_merge($message->headerValues[$normalized], $value); + } else { + $message->headerNames[$normalized] = $name; + $message->headerValues[$normalized] = $value; + } + + return $message; + } + + public function withoutHeader($name) + { + $normalized = strtolower(rtrim($name)); + + $message = clone $this; + unset($message->headerNames[$normalized]); + unset($message->headerValues[$normalized]); + + return $message; + } + + public function getBody() + { + return $this->body; + } + + public function withBody(StreamInterface $body) + { + $message = clone $this; + $message->body = $body; + + return $message; + } + + protected function setHeaders(array $headers) + { + // Prepare header field names and header field values according to + // https://tools.ietf.org/html/rfc7230#section-3.2.4 + $names = array_map('rtrim', array_keys($headers)); + $values = $this->normalizeHeaderValues($headers); + + $normalized = array_map('strtolower', $names); + + $this->headerNames = array_combine( + $normalized, + $names + ); + + $this->headerValues = array_combine( + $normalized, + $values + ); + } + + protected function normalizeHeaderValues(array $values) + { + // Prepare header field names and header field values according to + // https://tools.ietf.org/html/rfc7230#section-3.2.4 + return array_map(function ($value) { + if (! is_array($value)) { + $value = [$value]; + } + + return array_map(function ($value) { + return trim($value, " \t"); + }, $value); + }, $values); + } +} diff --git a/library/vendor/iplx/Http/Request.php b/library/vendor/iplx/Http/Request.php new file mode 100644 index 0000000..b9fae7d --- /dev/null +++ b/library/vendor/iplx/Http/Request.php @@ -0,0 +1,143 @@ +method = $method; + $this->uri = new Uri($uri); + $this->setHeaders($headers); + $this->body = Stream::create($body); + $this->protocolVersion = $protocolVersion; + + $this->provideHostHeader(); + } + + public function getRequestTarget() + { + if ($this->requestTarget !== null) { + return $this->requestTarget; + } + + $requestTarget = $this->uri->getPath(); + + // Weak type checks to also check null + + if ($requestTarget == '') { + $requestTarget = '/'; + } + + if ($this->uri->getQuery() != '') { + $requestTarget .= '?' . $this->uri->getQuery(); + } + + return $requestTarget; + } + + public function withRequestTarget($requestTarget) + { + $request = clone $this; + $request->requestTarget = $requestTarget; + + return $request; + } + + public function getMethod() + { + return $this->method; + } + + public function withMethod($method) + { + $request = clone $this; + $request->method = $method; + + return $this; + } + + public function getUri() + { + return $this->uri; + } + + public function withUri(UriInterface $uri, $preserveHost = false) + { + $request = clone $this; + $request->uri = $uri; + + if (! $preserveHost) { + $this->provideHostHeader(true); + } + + return $this; + } + + protected function provideHostHeader($force = false) + { + if ($this->hasHeader('host')) { + if (! $force) { + return; + } + + $header = $this->headerNames['host']; + } else { + $header = 'Host'; + } + + $host = $this->uri->getHost(); + + // Weak type check to also check null + if ($host == '') { + $host = ''; + } else { + $port = $this->uri->getPort(); + + if ($port !== null) { + $host .= ":$port"; + } + } + + $this->headerNames['host'] = $header; + $this->headerValues['host'] = [$host]; + } +} diff --git a/library/vendor/iplx/Http/Response.php b/library/vendor/iplx/Http/Response.php new file mode 100644 index 0000000..25448b1 --- /dev/null +++ b/library/vendor/iplx/Http/Response.php @@ -0,0 +1,64 @@ +statusCode = $statusCode; + $this->setHeaders($headers); + $this->body = Stream::create($body); + $this->protocolVersion = $protocolVersion; + $this->reasonPhrase = $reasonPhrase; + } + + public function getStatusCode() + { + return $this->statusCode; + } + + public function withStatus($code, $reasonPhrase = '') + { + $response = clone $this; + $response->statusCode = $code; + $response->reasonPhrase = $reasonPhrase; + + return $response; + } + + public function getReasonPhrase() + { + return $this->reasonPhrase; + } +} diff --git a/library/vendor/iplx/Http/Stream.php b/library/vendor/iplx/Http/Stream.php new file mode 100644 index 0000000..a113312 --- /dev/null +++ b/library/vendor/iplx/Http/Stream.php @@ -0,0 +1,283 @@ +stream = $stream; + + $meta = stream_get_meta_data($this->stream); + $this->seekable = $meta['seekable']; + $this->readable = preg_match('/[r+]/', $meta['mode']) === 1; + $this->writable = preg_match('/[waxc+]/', $meta['mode']) === 1; + } + + public function __destruct() + { + $this->close(); + } + + public function __toString() + { + try { + $this->seek(0); + $contents = stream_get_contents($this->stream); + } catch (Exception $e) { + $contents = ''; + } + + return $contents; + } + + public function close() + { + if (isset($this->stream)) { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->detach(); + } + } + + public function detach() + { + if (! isset($this->stream)) { + return null; + } + + $stream = $this->stream; + + $this->stream = null; + $this->size = null; + $this->seekable = false; + $this->readable = false; + $this->writable = false; + + return $stream; + } + + public function getSize() + { + if ($this->size !== null) { + return $this->size; + } + + if (! isset($this->stream)) { + return null; + } + + $stats = fstat($this->stream); + $this->size = $stats['size']; + + return $this->size; + } + + public function tell() + { + $this->assertAttached(); + + $position = ftell($this->stream); + + if ($position === false) { + throw new RuntimeException('Unable to determine stream position'); + } + + return $position; + } + + public function eof() + { + $this->assertAttached(); + + return feof($this->stream); + } + + public function isSeekable() + { + return $this->seekable; + } + + public function seek($offset, $whence = SEEK_SET) + { + $this->assertSeekable(); + + if (fseek($this->stream, $offset, $whence) === -1) { + throw new RuntimeException('Unable to seek to stream position'); + } + } + + public function rewind() + { + $this->seek(0); + } + + public function isWritable() + { + return $this->writable; + } + + public function write($string) + { + $this->assertWritable(); + + $written = fwrite($this->stream, $string); + + if ($written === false) { + throw new RuntimeException('Unable to write to stream'); + } + + return $written; + } + + public function isReadable() + { + return $this->readable; + } + + public function read($length) + { + $this->assertReadable(); + + $data = fread($this->stream, $length); + + if ($data === false) { + throw new RuntimeException('Unable to read from stream'); + } + + return $data; + } + + public function getContents() + { + $this->assertReadable(); + + $contents = stream_get_contents($this->stream); + + if ($contents === false) { + throw new RuntimeException('Unable to read stream contents'); + } + + return $contents; + } + + public function getMetadata($key = null) + { + if (! isset($this->stream)) { + return $key === null ? [] : null; + } + + $meta = stream_get_meta_data($this->stream); + + if ($key === null) { + return $meta; + } + + if (isset($meta[$key])) { + return $meta[$key]; + } + + return null; + } + + public function assertAttached() + { + if (! isset($this->stream)) { + throw new RuntimeException('Stream is detached'); + } + } + + public function assertSeekable() + { + $this->assertAttached(); + + if (! $this->isSeekable()) { + throw new RuntimeException('Stream is not seekable'); + } + } + + public function assertReadable() + { + $this->assertAttached(); + + if (! $this->isReadable()) { + throw new RuntimeException('Stream is not readable'); + } + } + + public function assertWritable() + { + $this->assertAttached(); + + if (! $this->isWritable()) { + throw new RuntimeException('Stream is not writable'); + } + } + + /** + * Open a stream + * + * @param string $filename + * @param string $mode + * + * @return static + */ + public static function open($filename = 'php://temp', $mode = 'r+') + { + $stream = fopen($filename, $mode); + + return new static($stream); + } + + /** + * Create a stream + * + * @param StreamInterface|string|resource $resource + * + * @return StreamInterface + */ + public static function create($resource) + { + if ($resource instanceof StreamInterface) { + return $resource; + } + + if (is_scalar($resource)) { + $stream = fopen('php://temp', 'r+'); + + if ($resource !== '') { + fwrite($stream, $resource); + fseek($stream, 0); + } + + return new static($stream); + } + + if (is_resource($resource)) { + return new static($resource); + } + + return static::open(); + } + +} diff --git a/library/vendor/iplx/Http/Uri.php b/library/vendor/iplx/Http/Uri.php new file mode 100644 index 0000000..044fb17 --- /dev/null +++ b/library/vendor/iplx/Http/Uri.php @@ -0,0 +1,202 @@ + $value) { + $this->$component = $value; + } + } + + public function getScheme() + { + return $this->scheme; + } + + public function getAuthority() + { + // Weak type check to also check null + if ($this->host == '') { + return ''; + } + + $authority = $this->host; + + $userInfo = $this->getUserInfo(); + $port = $this->getPort(); + + if ($userInfo) { + $authority = "$userInfo@$authority"; + } + + if ($port !== null) { + $authority .= ":$port"; + } + + return $authority; + } + + public function getUserInfo() + { + $userInfo = $this->user; + + if ($this->pass !== null) { + $userInfo .= ":{$this->pass}"; + } + + return $userInfo; + } + + public function getHost() + { + return $this->host; + } + + public function getPort() + { + return $this->port; + } + + public function getPath() + { + return $this->path; + } + + public function getQuery() + { + return $this->query; + } + + public function getFragment() + { + return $this->fragment; + } + + public function withScheme($scheme) + { + $uri = clone $this; + $uri->scheme = $scheme; + + return $uri; + } + + public function withUserInfo($user, $password = null) + { + $uri = clone $this; + $uri->user = $user; + $uri->pass = $password; + + return $uri; + } + + public function withHost($host) + { + $uri = clone $this; + $uri->host = $host; + + return $uri; + } + + public function withPort($port) + { + $uri = clone $this; + $uri->port = $port; + + return $uri; + } + + public function withPath($path) + { + $uri = clone $this; + $uri->path = $path; + + return $uri; + } + + public function withQuery($query) + { + $uri = clone $this; + $uri->query = $query; + + return $uri; + } + + public function withFragment($fragment) + { + $uri = clone $this; + $uri->fragment = $fragment; + + return $uri; + } + + public function __toString() + { + $scheme = $this->getScheme(); + $authority = $this->getAuthority(); + $path = $this->getPath(); + $query = $this->getQuery(); + $fragment = $this->getFragment(); + + $uri = ''; + + // Weak type checks to also check null + + if ($scheme != '') { + $uri = "$scheme:"; + } + + if ($authority != '') { + $uri .= "//$authority"; + } + + if ($path != '') { + if ($path[0] === '/') { + if ($authority == '') { + $path = ltrim($path, '/'); + } + } else { + $path = "/$path"; + } + + $uri .= $path; + } + + if ($query != '') { + $uri .= "?$query"; + } + + if ($fragment != '') { + $uri .= "#$fragment"; + } + + return $uri; + } +} -- cgit v1.2.3