Completed
Pull Request — master (#359)
by Maxence
41s
created
lib/Vendor/GuzzleHttp/ClientInterface.php 2 patches
Indentation   +63 added lines, -63 removed lines patch added patch discarded remove patch
@@ -13,72 +13,72 @@
 block discarded – undo
13 13
  */
14 14
 interface ClientInterface
15 15
 {
16
-    /**
17
-     * The Guzzle major version.
18
-     */
19
-    public const MAJOR_VERSION = 7;
16
+	/**
17
+	 * The Guzzle major version.
18
+	 */
19
+	public const MAJOR_VERSION = 7;
20 20
 
21
-    /**
22
-     * Send an HTTP request.
23
-     *
24
-     * @param RequestInterface $request Request to send
25
-     * @param array            $options Request options to apply to the given
26
-     *                                  request and to the transfer.
27
-     *
28
-     * @throws GuzzleException
29
-     */
30
-    public function send(RequestInterface $request, array $options = []): ResponseInterface;
21
+	/**
22
+	 * Send an HTTP request.
23
+	 *
24
+	 * @param RequestInterface $request Request to send
25
+	 * @param array            $options Request options to apply to the given
26
+	 *                                  request and to the transfer.
27
+	 *
28
+	 * @throws GuzzleException
29
+	 */
30
+	public function send(RequestInterface $request, array $options = []): ResponseInterface;
31 31
 
32
-    /**
33
-     * Asynchronously send an HTTP request.
34
-     *
35
-     * @param RequestInterface $request Request to send
36
-     * @param array            $options Request options to apply to the given
37
-     *                                  request and to the transfer.
38
-     */
39
-    public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface;
32
+	/**
33
+	 * Asynchronously send an HTTP request.
34
+	 *
35
+	 * @param RequestInterface $request Request to send
36
+	 * @param array            $options Request options to apply to the given
37
+	 *                                  request and to the transfer.
38
+	 */
39
+	public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface;
40 40
 
41
-    /**
42
-     * Create and send an HTTP request.
43
-     *
44
-     * Use an absolute path to override the base path of the client, or a
45
-     * relative path to append to the base path of the client. The URL can
46
-     * contain the query string as well.
47
-     *
48
-     * @param string              $method  HTTP method.
49
-     * @param string|UriInterface $uri     URI object or string.
50
-     * @param array               $options Request options to apply.
51
-     *
52
-     * @throws GuzzleException
53
-     */
54
-    public function request(string $method, $uri, array $options = []): ResponseInterface;
41
+	/**
42
+	 * Create and send an HTTP request.
43
+	 *
44
+	 * Use an absolute path to override the base path of the client, or a
45
+	 * relative path to append to the base path of the client. The URL can
46
+	 * contain the query string as well.
47
+	 *
48
+	 * @param string              $method  HTTP method.
49
+	 * @param string|UriInterface $uri     URI object or string.
50
+	 * @param array               $options Request options to apply.
51
+	 *
52
+	 * @throws GuzzleException
53
+	 */
54
+	public function request(string $method, $uri, array $options = []): ResponseInterface;
55 55
 
56
-    /**
57
-     * Create and send an asynchronous HTTP request.
58
-     *
59
-     * Use an absolute path to override the base path of the client, or a
60
-     * relative path to append to the base path of the client. The URL can
61
-     * contain the query string as well. Use an array to provide a URL
62
-     * template and additional variables to use in the URL template expansion.
63
-     *
64
-     * @param string              $method  HTTP method
65
-     * @param string|UriInterface $uri     URI object or string.
66
-     * @param array               $options Request options to apply.
67
-     */
68
-    public function requestAsync(string $method, $uri, array $options = []): PromiseInterface;
56
+	/**
57
+	 * Create and send an asynchronous HTTP request.
58
+	 *
59
+	 * Use an absolute path to override the base path of the client, or a
60
+	 * relative path to append to the base path of the client. The URL can
61
+	 * contain the query string as well. Use an array to provide a URL
62
+	 * template and additional variables to use in the URL template expansion.
63
+	 *
64
+	 * @param string              $method  HTTP method
65
+	 * @param string|UriInterface $uri     URI object or string.
66
+	 * @param array               $options Request options to apply.
67
+	 */
68
+	public function requestAsync(string $method, $uri, array $options = []): PromiseInterface;
69 69
 
70
-    /**
71
-     * Get a client configuration option.
72
-     *
73
-     * These options include default request options of the client, a "handler"
74
-     * (if utilized by the concrete client), and a "base_uri" if utilized by
75
-     * the concrete client.
76
-     *
77
-     * @param string|null $option The config option to retrieve.
78
-     *
79
-     * @return mixed
80
-     *
81
-     * @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0.
82
-     */
83
-    public function getConfig(string $option = null);
70
+	/**
71
+	 * Get a client configuration option.
72
+	 *
73
+	 * These options include default request options of the client, a "handler"
74
+	 * (if utilized by the concrete client), and a "base_uri" if utilized by
75
+	 * the concrete client.
76
+	 *
77
+	 * @param string|null $option The config option to retrieve.
78
+	 *
79
+	 * @return mixed
80
+	 *
81
+	 * @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0.
82
+	 */
83
+	public function getConfig(string $option = null);
84 84
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -11,8 +11,7 @@
 block discarded – undo
11 11
 /**
12 12
  * Client interface for sending HTTP requests.
13 13
  */
14
-interface ClientInterface
15
-{
14
+interface ClientInterface {
16 15
     /**
17 16
      * The Guzzle major version.
18 17
      */
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/StreamHandler.php 3 patches
Indentation   +590 added lines, -590 removed lines patch added patch discarded remove patch
@@ -22,594 +22,594 @@
 block discarded – undo
22 22
  */
23 23
 class StreamHandler
24 24
 {
25
-    /**
26
-     * @var array
27
-     */
28
-    private $lastHeaders = [];
29
-
30
-    /**
31
-     * Sends an HTTP request.
32
-     *
33
-     * @param RequestInterface $request Request to send.
34
-     * @param array            $options Request transfer options.
35
-     */
36
-    public function __invoke(RequestInterface $request, array $options): PromiseInterface
37
-    {
38
-        // Sleep if there is a delay specified.
39
-        if (isset($options['delay'])) {
40
-            \usleep($options['delay'] * 1000);
41
-        }
42
-
43
-        $startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
44
-
45
-        try {
46
-            // Does not support the expect header.
47
-            $request = $request->withoutHeader('Expect');
48
-
49
-            // Append a content-length header if body size is zero to match
50
-            // cURL's behavior.
51
-            if (0 === $request->getBody()->getSize()) {
52
-                $request = $request->withHeader('Content-Length', '0');
53
-            }
54
-
55
-            return $this->createResponse(
56
-                $request,
57
-                $options,
58
-                $this->createStream($request, $options),
59
-                $startTime
60
-            );
61
-        } catch (\InvalidArgumentException $e) {
62
-            throw $e;
63
-        } catch (\Exception $e) {
64
-            // Determine if the error was a networking error.
65
-            $message = $e->getMessage();
66
-            // This list can probably get more comprehensive.
67
-            if (false !== \strpos($message, 'getaddrinfo') // DNS lookup failed
68
-                || false !== \strpos($message, 'Connection refused')
69
-                || false !== \strpos($message, "couldn't connect to host") // error on HHVM
70
-                || false !== \strpos($message, 'connection attempt failed')
71
-            ) {
72
-                $e = new ConnectException($e->getMessage(), $request, $e);
73
-            } else {
74
-                $e = RequestException::wrapException($request, $e);
75
-            }
76
-            $this->invokeStats($options, $request, $startTime, null, $e);
77
-
78
-            return P\Create::rejectionFor($e);
79
-        }
80
-    }
81
-
82
-    private function invokeStats(
83
-        array $options,
84
-        RequestInterface $request,
85
-        ?float $startTime,
86
-        ResponseInterface $response = null,
87
-        \Throwable $error = null
88
-    ): void {
89
-        if (isset($options['on_stats'])) {
90
-            $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []);
91
-            ($options['on_stats'])($stats);
92
-        }
93
-    }
94
-
95
-    /**
96
-     * @param resource $stream
97
-     */
98
-    private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime): PromiseInterface
99
-    {
100
-        $hdrs = $this->lastHeaders;
101
-        $this->lastHeaders = [];
102
-
103
-        try {
104
-            [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs);
105
-        } catch (\Exception $e) {
106
-            return P\Create::rejectionFor(
107
-                new RequestException('An error was encountered while creating the response', $request, null, $e)
108
-            );
109
-        }
110
-
111
-        [$stream, $headers] = $this->checkDecode($options, $headers, $stream);
112
-        $stream = Psr7\Utils::streamFor($stream);
113
-        $sink = $stream;
114
-
115
-        if (\strcasecmp('HEAD', $request->getMethod())) {
116
-            $sink = $this->createSink($stream, $options);
117
-        }
118
-
119
-        try {
120
-            $response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
121
-        } catch (\Exception $e) {
122
-            return P\Create::rejectionFor(
123
-                new RequestException('An error was encountered while creating the response', $request, null, $e)
124
-            );
125
-        }
126
-
127
-        if (isset($options['on_headers'])) {
128
-            try {
129
-                $options['on_headers']($response);
130
-            } catch (\Exception $e) {
131
-                return P\Create::rejectionFor(
132
-                    new RequestException('An error was encountered during the on_headers event', $request, $response, $e)
133
-                );
134
-            }
135
-        }
136
-
137
-        // Do not drain when the request is a HEAD request because they have
138
-        // no body.
139
-        if ($sink !== $stream) {
140
-            $this->drain($stream, $sink, $response->getHeaderLine('Content-Length'));
141
-        }
142
-
143
-        $this->invokeStats($options, $request, $startTime, $response, null);
144
-
145
-        return new FulfilledPromise($response);
146
-    }
147
-
148
-    private function createSink(StreamInterface $stream, array $options): StreamInterface
149
-    {
150
-        if (!empty($options['stream'])) {
151
-            return $stream;
152
-        }
153
-
154
-        $sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+');
155
-
156
-        return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink);
157
-    }
158
-
159
-    /**
160
-     * @param resource $stream
161
-     */
162
-    private function checkDecode(array $options, array $headers, $stream): array
163
-    {
164
-        // Automatically decode responses when instructed.
165
-        if (!empty($options['decode_content'])) {
166
-            $normalizedKeys = Utils::normalizeHeaderKeys($headers);
167
-            if (isset($normalizedKeys['content-encoding'])) {
168
-                $encoding = $headers[$normalizedKeys['content-encoding']];
169
-                if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
170
-                    $stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream));
171
-                    $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
172
-
173
-                    // Remove content-encoding header
174
-                    unset($headers[$normalizedKeys['content-encoding']]);
175
-
176
-                    // Fix content-length header
177
-                    if (isset($normalizedKeys['content-length'])) {
178
-                        $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
179
-                        $length = (int) $stream->getSize();
180
-                        if ($length === 0) {
181
-                            unset($headers[$normalizedKeys['content-length']]);
182
-                        } else {
183
-                            $headers[$normalizedKeys['content-length']] = [$length];
184
-                        }
185
-                    }
186
-                }
187
-            }
188
-        }
189
-
190
-        return [$stream, $headers];
191
-    }
192
-
193
-    /**
194
-     * Drains the source stream into the "sink" client option.
195
-     *
196
-     * @param string $contentLength Header specifying the amount of
197
-     *                              data to read.
198
-     *
199
-     * @throws \RuntimeException when the sink option is invalid.
200
-     */
201
-    private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength): StreamInterface
202
-    {
203
-        // If a content-length header is provided, then stop reading once
204
-        // that number of bytes has been read. This can prevent infinitely
205
-        // reading from a stream when dealing with servers that do not honor
206
-        // Connection: Close headers.
207
-        Psr7\Utils::copyToStream(
208
-            $source,
209
-            $sink,
210
-            (\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
211
-        );
212
-
213
-        $sink->seek(0);
214
-        $source->close();
215
-
216
-        return $sink;
217
-    }
218
-
219
-    /**
220
-     * Create a resource and check to ensure it was created successfully
221
-     *
222
-     * @param callable $callback Callable that returns stream resource
223
-     *
224
-     * @return resource
225
-     *
226
-     * @throws \RuntimeException on error
227
-     */
228
-    private function createResource(callable $callback)
229
-    {
230
-        $errors = [];
231
-        \set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool {
232
-            $errors[] = [
233
-                'message' => $msg,
234
-                'file' => $file,
235
-                'line' => $line,
236
-            ];
237
-
238
-            return true;
239
-        });
240
-
241
-        try {
242
-            $resource = $callback();
243
-        } finally {
244
-            \restore_error_handler();
245
-        }
246
-
247
-        if (!$resource) {
248
-            $message = 'Error creating resource: ';
249
-            foreach ($errors as $err) {
250
-                foreach ($err as $key => $value) {
251
-                    $message .= "[$key] $value".\PHP_EOL;
252
-                }
253
-            }
254
-            throw new \RuntimeException(\trim($message));
255
-        }
256
-
257
-        return $resource;
258
-    }
259
-
260
-    /**
261
-     * @return resource
262
-     */
263
-    private function createStream(RequestInterface $request, array $options)
264
-    {
265
-        static $methods;
266
-        if (!$methods) {
267
-            $methods = \array_flip(\get_class_methods(__CLASS__));
268
-        }
269
-
270
-        if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) {
271
-            throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request);
272
-        }
273
-
274
-        // HTTP/1.1 streams using the PHP stream wrapper require a
275
-        // Connection: close header
276
-        if ($request->getProtocolVersion() == '1.1'
277
-            && !$request->hasHeader('Connection')
278
-        ) {
279
-            $request = $request->withHeader('Connection', 'close');
280
-        }
281
-
282
-        // Ensure SSL is verified by default
283
-        if (!isset($options['verify'])) {
284
-            $options['verify'] = true;
285
-        }
286
-
287
-        $params = [];
288
-        $context = $this->getDefaultContext($request);
289
-
290
-        if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) {
291
-            throw new \InvalidArgumentException('on_headers must be callable');
292
-        }
293
-
294
-        if (!empty($options)) {
295
-            foreach ($options as $key => $value) {
296
-                $method = "add_{$key}";
297
-                if (isset($methods[$method])) {
298
-                    $this->{$method}($request, $context, $value, $params);
299
-                }
300
-            }
301
-        }
302
-
303
-        if (isset($options['stream_context'])) {
304
-            if (!\is_array($options['stream_context'])) {
305
-                throw new \InvalidArgumentException('stream_context must be an array');
306
-            }
307
-            $context = \array_replace_recursive($context, $options['stream_context']);
308
-        }
309
-
310
-        // Microsoft NTLM authentication only supported with curl handler
311
-        if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) {
312
-            throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
313
-        }
314
-
315
-        $uri = $this->resolveHost($request, $options);
316
-
317
-        $contextResource = $this->createResource(
318
-            static function () use ($context, $params) {
319
-                return \stream_context_create($context, $params);
320
-            }
321
-        );
322
-
323
-        return $this->createResource(
324
-            function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) {
325
-                $resource = @\fopen((string) $uri, 'r', false, $contextResource);
326
-                $this->lastHeaders = $http_response_header ?? [];
327
-
328
-                if (false === $resource) {
329
-                    throw new ConnectException(sprintf('Connection refused for URI %s', $uri), $request, null, $context);
330
-                }
331
-
332
-                if (isset($options['read_timeout'])) {
333
-                    $readTimeout = $options['read_timeout'];
334
-                    $sec = (int) $readTimeout;
335
-                    $usec = ($readTimeout - $sec) * 100000;
336
-                    \stream_set_timeout($resource, $sec, $usec);
337
-                }
338
-
339
-                return $resource;
340
-            }
341
-        );
342
-    }
343
-
344
-    private function resolveHost(RequestInterface $request, array $options): UriInterface
345
-    {
346
-        $uri = $request->getUri();
347
-
348
-        if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) {
349
-            if ('v4' === $options['force_ip_resolve']) {
350
-                $records = \dns_get_record($uri->getHost(), \DNS_A);
351
-                if (false === $records || !isset($records[0]['ip'])) {
352
-                    throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
353
-                }
354
-
355
-                return $uri->withHost($records[0]['ip']);
356
-            }
357
-            if ('v6' === $options['force_ip_resolve']) {
358
-                $records = \dns_get_record($uri->getHost(), \DNS_AAAA);
359
-                if (false === $records || !isset($records[0]['ipv6'])) {
360
-                    throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
361
-                }
362
-
363
-                return $uri->withHost('['.$records[0]['ipv6'].']');
364
-            }
365
-        }
366
-
367
-        return $uri;
368
-    }
369
-
370
-    private function getDefaultContext(RequestInterface $request): array
371
-    {
372
-        $headers = '';
373
-        foreach ($request->getHeaders() as $name => $value) {
374
-            foreach ($value as $val) {
375
-                $headers .= "$name: $val\r\n";
376
-            }
377
-        }
378
-
379
-        $context = [
380
-            'http' => [
381
-                'method' => $request->getMethod(),
382
-                'header' => $headers,
383
-                'protocol_version' => $request->getProtocolVersion(),
384
-                'ignore_errors' => true,
385
-                'follow_location' => 0,
386
-            ],
387
-            'ssl' => [
388
-                'peer_name' => $request->getUri()->getHost(),
389
-            ],
390
-        ];
391
-
392
-        $body = (string) $request->getBody();
393
-
394
-        if ('' !== $body) {
395
-            $context['http']['content'] = $body;
396
-            // Prevent the HTTP handler from adding a Content-Type header.
397
-            if (!$request->hasHeader('Content-Type')) {
398
-                $context['http']['header'] .= "Content-Type:\r\n";
399
-            }
400
-        }
401
-
402
-        $context['http']['header'] = \rtrim($context['http']['header']);
403
-
404
-        return $context;
405
-    }
406
-
407
-    /**
408
-     * @param mixed $value as passed via Request transfer options.
409
-     */
410
-    private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): void
411
-    {
412
-        $uri = null;
413
-
414
-        if (!\is_array($value)) {
415
-            $uri = $value;
416
-        } else {
417
-            $scheme = $request->getUri()->getScheme();
418
-            if (isset($value[$scheme])) {
419
-                if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) {
420
-                    $uri = $value[$scheme];
421
-                }
422
-            }
423
-        }
424
-
425
-        if (!$uri) {
426
-            return;
427
-        }
428
-
429
-        $parsed = $this->parse_proxy($uri);
430
-        $options['http']['proxy'] = $parsed['proxy'];
431
-
432
-        if ($parsed['auth']) {
433
-            if (!isset($options['http']['header'])) {
434
-                $options['http']['header'] = [];
435
-            }
436
-            $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}";
437
-        }
438
-    }
439
-
440
-    /**
441
-     * Parses the given proxy URL to make it compatible with the format PHP's stream context expects.
442
-     */
443
-    private function parse_proxy(string $url): array
444
-    {
445
-        $parsed = \parse_url($url);
446
-
447
-        if ($parsed !== false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') {
448
-            if (isset($parsed['host']) && isset($parsed['port'])) {
449
-                $auth = null;
450
-                if (isset($parsed['user']) && isset($parsed['pass'])) {
451
-                    $auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}");
452
-                }
453
-
454
-                return [
455
-                    'proxy' => "tcp://{$parsed['host']}:{$parsed['port']}",
456
-                    'auth' => $auth ? "Basic {$auth}" : null,
457
-                ];
458
-            }
459
-        }
460
-
461
-        // Return proxy as-is.
462
-        return [
463
-            'proxy' => $url,
464
-            'auth' => null,
465
-        ];
466
-    }
467
-
468
-    /**
469
-     * @param mixed $value as passed via Request transfer options.
470
-     */
471
-    private function add_timeout(RequestInterface $request, array &$options, $value, array &$params): void
472
-    {
473
-        if ($value > 0) {
474
-            $options['http']['timeout'] = $value;
475
-        }
476
-    }
477
-
478
-    /**
479
-     * @param mixed $value as passed via Request transfer options.
480
-     */
481
-    private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params): void
482
-    {
483
-        if (
484
-            $value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
485
-            || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
486
-            || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
487
-            || (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT)
488
-        ) {
489
-            $options['http']['crypto_method'] = $value;
490
-
491
-            return;
492
-        }
493
-
494
-        throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
495
-    }
496
-
497
-    /**
498
-     * @param mixed $value as passed via Request transfer options.
499
-     */
500
-    private function add_verify(RequestInterface $request, array &$options, $value, array &$params): void
501
-    {
502
-        if ($value === false) {
503
-            $options['ssl']['verify_peer'] = false;
504
-            $options['ssl']['verify_peer_name'] = false;
505
-
506
-            return;
507
-        }
508
-
509
-        if (\is_string($value)) {
510
-            $options['ssl']['cafile'] = $value;
511
-            if (!\file_exists($value)) {
512
-                throw new \RuntimeException("SSL CA bundle not found: $value");
513
-            }
514
-        } elseif ($value !== true) {
515
-            throw new \InvalidArgumentException('Invalid verify request option');
516
-        }
517
-
518
-        $options['ssl']['verify_peer'] = true;
519
-        $options['ssl']['verify_peer_name'] = true;
520
-        $options['ssl']['allow_self_signed'] = false;
521
-    }
522
-
523
-    /**
524
-     * @param mixed $value as passed via Request transfer options.
525
-     */
526
-    private function add_cert(RequestInterface $request, array &$options, $value, array &$params): void
527
-    {
528
-        if (\is_array($value)) {
529
-            $options['ssl']['passphrase'] = $value[1];
530
-            $value = $value[0];
531
-        }
532
-
533
-        if (!\file_exists($value)) {
534
-            throw new \RuntimeException("SSL certificate not found: {$value}");
535
-        }
536
-
537
-        $options['ssl']['local_cert'] = $value;
538
-    }
539
-
540
-    /**
541
-     * @param mixed $value as passed via Request transfer options.
542
-     */
543
-    private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void
544
-    {
545
-        self::addNotification(
546
-            $params,
547
-            static function ($code, $a, $b, $c, $transferred, $total) use ($value) {
548
-                if ($code == \STREAM_NOTIFY_PROGRESS) {
549
-                    // The upload progress cannot be determined. Use 0 for cURL compatibility:
550
-                    // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
551
-                    $value($total, $transferred, 0, 0);
552
-                }
553
-            }
554
-        );
555
-    }
556
-
557
-    /**
558
-     * @param mixed $value as passed via Request transfer options.
559
-     */
560
-    private function add_debug(RequestInterface $request, array &$options, $value, array &$params): void
561
-    {
562
-        if ($value === false) {
563
-            return;
564
-        }
565
-
566
-        static $map = [
567
-            \STREAM_NOTIFY_CONNECT => 'CONNECT',
568
-            \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
569
-            \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
570
-            \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
571
-            \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
572
-            \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
573
-            \STREAM_NOTIFY_PROGRESS => 'PROGRESS',
574
-            \STREAM_NOTIFY_FAILURE => 'FAILURE',
575
-            \STREAM_NOTIFY_COMPLETED => 'COMPLETED',
576
-            \STREAM_NOTIFY_RESOLVE => 'RESOLVE',
577
-        ];
578
-        static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
579
-
580
-        $value = Utils::debugResource($value);
581
-        $ident = $request->getMethod().' '.$request->getUri()->withFragment('');
582
-        self::addNotification(
583
-            $params,
584
-            static function (int $code, ...$passed) use ($ident, $value, $map, $args): void {
585
-                \fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
586
-                foreach (\array_filter($passed) as $i => $v) {
587
-                    \fwrite($value, $args[$i].': "'.$v.'" ');
588
-                }
589
-                \fwrite($value, "\n");
590
-            }
591
-        );
592
-    }
593
-
594
-    private static function addNotification(array &$params, callable $notify): void
595
-    {
596
-        // Wrap the existing function if needed.
597
-        if (!isset($params['notification'])) {
598
-            $params['notification'] = $notify;
599
-        } else {
600
-            $params['notification'] = self::callArray([
601
-                $params['notification'],
602
-                $notify,
603
-            ]);
604
-        }
605
-    }
606
-
607
-    private static function callArray(array $functions): callable
608
-    {
609
-        return static function (...$args) use ($functions) {
610
-            foreach ($functions as $fn) {
611
-                $fn(...$args);
612
-            }
613
-        };
614
-    }
25
+	/**
26
+	 * @var array
27
+	 */
28
+	private $lastHeaders = [];
29
+
30
+	/**
31
+	 * Sends an HTTP request.
32
+	 *
33
+	 * @param RequestInterface $request Request to send.
34
+	 * @param array            $options Request transfer options.
35
+	 */
36
+	public function __invoke(RequestInterface $request, array $options): PromiseInterface
37
+	{
38
+		// Sleep if there is a delay specified.
39
+		if (isset($options['delay'])) {
40
+			\usleep($options['delay'] * 1000);
41
+		}
42
+
43
+		$startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
44
+
45
+		try {
46
+			// Does not support the expect header.
47
+			$request = $request->withoutHeader('Expect');
48
+
49
+			// Append a content-length header if body size is zero to match
50
+			// cURL's behavior.
51
+			if (0 === $request->getBody()->getSize()) {
52
+				$request = $request->withHeader('Content-Length', '0');
53
+			}
54
+
55
+			return $this->createResponse(
56
+				$request,
57
+				$options,
58
+				$this->createStream($request, $options),
59
+				$startTime
60
+			);
61
+		} catch (\InvalidArgumentException $e) {
62
+			throw $e;
63
+		} catch (\Exception $e) {
64
+			// Determine if the error was a networking error.
65
+			$message = $e->getMessage();
66
+			// This list can probably get more comprehensive.
67
+			if (false !== \strpos($message, 'getaddrinfo') // DNS lookup failed
68
+				|| false !== \strpos($message, 'Connection refused')
69
+				|| false !== \strpos($message, "couldn't connect to host") // error on HHVM
70
+				|| false !== \strpos($message, 'connection attempt failed')
71
+			) {
72
+				$e = new ConnectException($e->getMessage(), $request, $e);
73
+			} else {
74
+				$e = RequestException::wrapException($request, $e);
75
+			}
76
+			$this->invokeStats($options, $request, $startTime, null, $e);
77
+
78
+			return P\Create::rejectionFor($e);
79
+		}
80
+	}
81
+
82
+	private function invokeStats(
83
+		array $options,
84
+		RequestInterface $request,
85
+		?float $startTime,
86
+		ResponseInterface $response = null,
87
+		\Throwable $error = null
88
+	): void {
89
+		if (isset($options['on_stats'])) {
90
+			$stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []);
91
+			($options['on_stats'])($stats);
92
+		}
93
+	}
94
+
95
+	/**
96
+	 * @param resource $stream
97
+	 */
98
+	private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime): PromiseInterface
99
+	{
100
+		$hdrs = $this->lastHeaders;
101
+		$this->lastHeaders = [];
102
+
103
+		try {
104
+			[$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs);
105
+		} catch (\Exception $e) {
106
+			return P\Create::rejectionFor(
107
+				new RequestException('An error was encountered while creating the response', $request, null, $e)
108
+			);
109
+		}
110
+
111
+		[$stream, $headers] = $this->checkDecode($options, $headers, $stream);
112
+		$stream = Psr7\Utils::streamFor($stream);
113
+		$sink = $stream;
114
+
115
+		if (\strcasecmp('HEAD', $request->getMethod())) {
116
+			$sink = $this->createSink($stream, $options);
117
+		}
118
+
119
+		try {
120
+			$response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
121
+		} catch (\Exception $e) {
122
+			return P\Create::rejectionFor(
123
+				new RequestException('An error was encountered while creating the response', $request, null, $e)
124
+			);
125
+		}
126
+
127
+		if (isset($options['on_headers'])) {
128
+			try {
129
+				$options['on_headers']($response);
130
+			} catch (\Exception $e) {
131
+				return P\Create::rejectionFor(
132
+					new RequestException('An error was encountered during the on_headers event', $request, $response, $e)
133
+				);
134
+			}
135
+		}
136
+
137
+		// Do not drain when the request is a HEAD request because they have
138
+		// no body.
139
+		if ($sink !== $stream) {
140
+			$this->drain($stream, $sink, $response->getHeaderLine('Content-Length'));
141
+		}
142
+
143
+		$this->invokeStats($options, $request, $startTime, $response, null);
144
+
145
+		return new FulfilledPromise($response);
146
+	}
147
+
148
+	private function createSink(StreamInterface $stream, array $options): StreamInterface
149
+	{
150
+		if (!empty($options['stream'])) {
151
+			return $stream;
152
+		}
153
+
154
+		$sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+');
155
+
156
+		return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink);
157
+	}
158
+
159
+	/**
160
+	 * @param resource $stream
161
+	 */
162
+	private function checkDecode(array $options, array $headers, $stream): array
163
+	{
164
+		// Automatically decode responses when instructed.
165
+		if (!empty($options['decode_content'])) {
166
+			$normalizedKeys = Utils::normalizeHeaderKeys($headers);
167
+			if (isset($normalizedKeys['content-encoding'])) {
168
+				$encoding = $headers[$normalizedKeys['content-encoding']];
169
+				if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
170
+					$stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream));
171
+					$headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
172
+
173
+					// Remove content-encoding header
174
+					unset($headers[$normalizedKeys['content-encoding']]);
175
+
176
+					// Fix content-length header
177
+					if (isset($normalizedKeys['content-length'])) {
178
+						$headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
179
+						$length = (int) $stream->getSize();
180
+						if ($length === 0) {
181
+							unset($headers[$normalizedKeys['content-length']]);
182
+						} else {
183
+							$headers[$normalizedKeys['content-length']] = [$length];
184
+						}
185
+					}
186
+				}
187
+			}
188
+		}
189
+
190
+		return [$stream, $headers];
191
+	}
192
+
193
+	/**
194
+	 * Drains the source stream into the "sink" client option.
195
+	 *
196
+	 * @param string $contentLength Header specifying the amount of
197
+	 *                              data to read.
198
+	 *
199
+	 * @throws \RuntimeException when the sink option is invalid.
200
+	 */
201
+	private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength): StreamInterface
202
+	{
203
+		// If a content-length header is provided, then stop reading once
204
+		// that number of bytes has been read. This can prevent infinitely
205
+		// reading from a stream when dealing with servers that do not honor
206
+		// Connection: Close headers.
207
+		Psr7\Utils::copyToStream(
208
+			$source,
209
+			$sink,
210
+			(\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
211
+		);
212
+
213
+		$sink->seek(0);
214
+		$source->close();
215
+
216
+		return $sink;
217
+	}
218
+
219
+	/**
220
+	 * Create a resource and check to ensure it was created successfully
221
+	 *
222
+	 * @param callable $callback Callable that returns stream resource
223
+	 *
224
+	 * @return resource
225
+	 *
226
+	 * @throws \RuntimeException on error
227
+	 */
228
+	private function createResource(callable $callback)
229
+	{
230
+		$errors = [];
231
+		\set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool {
232
+			$errors[] = [
233
+				'message' => $msg,
234
+				'file' => $file,
235
+				'line' => $line,
236
+			];
237
+
238
+			return true;
239
+		});
240
+
241
+		try {
242
+			$resource = $callback();
243
+		} finally {
244
+			\restore_error_handler();
245
+		}
246
+
247
+		if (!$resource) {
248
+			$message = 'Error creating resource: ';
249
+			foreach ($errors as $err) {
250
+				foreach ($err as $key => $value) {
251
+					$message .= "[$key] $value".\PHP_EOL;
252
+				}
253
+			}
254
+			throw new \RuntimeException(\trim($message));
255
+		}
256
+
257
+		return $resource;
258
+	}
259
+
260
+	/**
261
+	 * @return resource
262
+	 */
263
+	private function createStream(RequestInterface $request, array $options)
264
+	{
265
+		static $methods;
266
+		if (!$methods) {
267
+			$methods = \array_flip(\get_class_methods(__CLASS__));
268
+		}
269
+
270
+		if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) {
271
+			throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request);
272
+		}
273
+
274
+		// HTTP/1.1 streams using the PHP stream wrapper require a
275
+		// Connection: close header
276
+		if ($request->getProtocolVersion() == '1.1'
277
+			&& !$request->hasHeader('Connection')
278
+		) {
279
+			$request = $request->withHeader('Connection', 'close');
280
+		}
281
+
282
+		// Ensure SSL is verified by default
283
+		if (!isset($options['verify'])) {
284
+			$options['verify'] = true;
285
+		}
286
+
287
+		$params = [];
288
+		$context = $this->getDefaultContext($request);
289
+
290
+		if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) {
291
+			throw new \InvalidArgumentException('on_headers must be callable');
292
+		}
293
+
294
+		if (!empty($options)) {
295
+			foreach ($options as $key => $value) {
296
+				$method = "add_{$key}";
297
+				if (isset($methods[$method])) {
298
+					$this->{$method}($request, $context, $value, $params);
299
+				}
300
+			}
301
+		}
302
+
303
+		if (isset($options['stream_context'])) {
304
+			if (!\is_array($options['stream_context'])) {
305
+				throw new \InvalidArgumentException('stream_context must be an array');
306
+			}
307
+			$context = \array_replace_recursive($context, $options['stream_context']);
308
+		}
309
+
310
+		// Microsoft NTLM authentication only supported with curl handler
311
+		if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) {
312
+			throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
313
+		}
314
+
315
+		$uri = $this->resolveHost($request, $options);
316
+
317
+		$contextResource = $this->createResource(
318
+			static function () use ($context, $params) {
319
+				return \stream_context_create($context, $params);
320
+			}
321
+		);
322
+
323
+		return $this->createResource(
324
+			function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) {
325
+				$resource = @\fopen((string) $uri, 'r', false, $contextResource);
326
+				$this->lastHeaders = $http_response_header ?? [];
327
+
328
+				if (false === $resource) {
329
+					throw new ConnectException(sprintf('Connection refused for URI %s', $uri), $request, null, $context);
330
+				}
331
+
332
+				if (isset($options['read_timeout'])) {
333
+					$readTimeout = $options['read_timeout'];
334
+					$sec = (int) $readTimeout;
335
+					$usec = ($readTimeout - $sec) * 100000;
336
+					\stream_set_timeout($resource, $sec, $usec);
337
+				}
338
+
339
+				return $resource;
340
+			}
341
+		);
342
+	}
343
+
344
+	private function resolveHost(RequestInterface $request, array $options): UriInterface
345
+	{
346
+		$uri = $request->getUri();
347
+
348
+		if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) {
349
+			if ('v4' === $options['force_ip_resolve']) {
350
+				$records = \dns_get_record($uri->getHost(), \DNS_A);
351
+				if (false === $records || !isset($records[0]['ip'])) {
352
+					throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
353
+				}
354
+
355
+				return $uri->withHost($records[0]['ip']);
356
+			}
357
+			if ('v6' === $options['force_ip_resolve']) {
358
+				$records = \dns_get_record($uri->getHost(), \DNS_AAAA);
359
+				if (false === $records || !isset($records[0]['ipv6'])) {
360
+					throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
361
+				}
362
+
363
+				return $uri->withHost('['.$records[0]['ipv6'].']');
364
+			}
365
+		}
366
+
367
+		return $uri;
368
+	}
369
+
370
+	private function getDefaultContext(RequestInterface $request): array
371
+	{
372
+		$headers = '';
373
+		foreach ($request->getHeaders() as $name => $value) {
374
+			foreach ($value as $val) {
375
+				$headers .= "$name: $val\r\n";
376
+			}
377
+		}
378
+
379
+		$context = [
380
+			'http' => [
381
+				'method' => $request->getMethod(),
382
+				'header' => $headers,
383
+				'protocol_version' => $request->getProtocolVersion(),
384
+				'ignore_errors' => true,
385
+				'follow_location' => 0,
386
+			],
387
+			'ssl' => [
388
+				'peer_name' => $request->getUri()->getHost(),
389
+			],
390
+		];
391
+
392
+		$body = (string) $request->getBody();
393
+
394
+		if ('' !== $body) {
395
+			$context['http']['content'] = $body;
396
+			// Prevent the HTTP handler from adding a Content-Type header.
397
+			if (!$request->hasHeader('Content-Type')) {
398
+				$context['http']['header'] .= "Content-Type:\r\n";
399
+			}
400
+		}
401
+
402
+		$context['http']['header'] = \rtrim($context['http']['header']);
403
+
404
+		return $context;
405
+	}
406
+
407
+	/**
408
+	 * @param mixed $value as passed via Request transfer options.
409
+	 */
410
+	private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): void
411
+	{
412
+		$uri = null;
413
+
414
+		if (!\is_array($value)) {
415
+			$uri = $value;
416
+		} else {
417
+			$scheme = $request->getUri()->getScheme();
418
+			if (isset($value[$scheme])) {
419
+				if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) {
420
+					$uri = $value[$scheme];
421
+				}
422
+			}
423
+		}
424
+
425
+		if (!$uri) {
426
+			return;
427
+		}
428
+
429
+		$parsed = $this->parse_proxy($uri);
430
+		$options['http']['proxy'] = $parsed['proxy'];
431
+
432
+		if ($parsed['auth']) {
433
+			if (!isset($options['http']['header'])) {
434
+				$options['http']['header'] = [];
435
+			}
436
+			$options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}";
437
+		}
438
+	}
439
+
440
+	/**
441
+	 * Parses the given proxy URL to make it compatible with the format PHP's stream context expects.
442
+	 */
443
+	private function parse_proxy(string $url): array
444
+	{
445
+		$parsed = \parse_url($url);
446
+
447
+		if ($parsed !== false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') {
448
+			if (isset($parsed['host']) && isset($parsed['port'])) {
449
+				$auth = null;
450
+				if (isset($parsed['user']) && isset($parsed['pass'])) {
451
+					$auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}");
452
+				}
453
+
454
+				return [
455
+					'proxy' => "tcp://{$parsed['host']}:{$parsed['port']}",
456
+					'auth' => $auth ? "Basic {$auth}" : null,
457
+				];
458
+			}
459
+		}
460
+
461
+		// Return proxy as-is.
462
+		return [
463
+			'proxy' => $url,
464
+			'auth' => null,
465
+		];
466
+	}
467
+
468
+	/**
469
+	 * @param mixed $value as passed via Request transfer options.
470
+	 */
471
+	private function add_timeout(RequestInterface $request, array &$options, $value, array &$params): void
472
+	{
473
+		if ($value > 0) {
474
+			$options['http']['timeout'] = $value;
475
+		}
476
+	}
477
+
478
+	/**
479
+	 * @param mixed $value as passed via Request transfer options.
480
+	 */
481
+	private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params): void
482
+	{
483
+		if (
484
+			$value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
485
+			|| $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
486
+			|| $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
487
+			|| (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT)
488
+		) {
489
+			$options['http']['crypto_method'] = $value;
490
+
491
+			return;
492
+		}
493
+
494
+		throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
495
+	}
496
+
497
+	/**
498
+	 * @param mixed $value as passed via Request transfer options.
499
+	 */
500
+	private function add_verify(RequestInterface $request, array &$options, $value, array &$params): void
501
+	{
502
+		if ($value === false) {
503
+			$options['ssl']['verify_peer'] = false;
504
+			$options['ssl']['verify_peer_name'] = false;
505
+
506
+			return;
507
+		}
508
+
509
+		if (\is_string($value)) {
510
+			$options['ssl']['cafile'] = $value;
511
+			if (!\file_exists($value)) {
512
+				throw new \RuntimeException("SSL CA bundle not found: $value");
513
+			}
514
+		} elseif ($value !== true) {
515
+			throw new \InvalidArgumentException('Invalid verify request option');
516
+		}
517
+
518
+		$options['ssl']['verify_peer'] = true;
519
+		$options['ssl']['verify_peer_name'] = true;
520
+		$options['ssl']['allow_self_signed'] = false;
521
+	}
522
+
523
+	/**
524
+	 * @param mixed $value as passed via Request transfer options.
525
+	 */
526
+	private function add_cert(RequestInterface $request, array &$options, $value, array &$params): void
527
+	{
528
+		if (\is_array($value)) {
529
+			$options['ssl']['passphrase'] = $value[1];
530
+			$value = $value[0];
531
+		}
532
+
533
+		if (!\file_exists($value)) {
534
+			throw new \RuntimeException("SSL certificate not found: {$value}");
535
+		}
536
+
537
+		$options['ssl']['local_cert'] = $value;
538
+	}
539
+
540
+	/**
541
+	 * @param mixed $value as passed via Request transfer options.
542
+	 */
543
+	private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void
544
+	{
545
+		self::addNotification(
546
+			$params,
547
+			static function ($code, $a, $b, $c, $transferred, $total) use ($value) {
548
+				if ($code == \STREAM_NOTIFY_PROGRESS) {
549
+					// The upload progress cannot be determined. Use 0 for cURL compatibility:
550
+					// https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
551
+					$value($total, $transferred, 0, 0);
552
+				}
553
+			}
554
+		);
555
+	}
556
+
557
+	/**
558
+	 * @param mixed $value as passed via Request transfer options.
559
+	 */
560
+	private function add_debug(RequestInterface $request, array &$options, $value, array &$params): void
561
+	{
562
+		if ($value === false) {
563
+			return;
564
+		}
565
+
566
+		static $map = [
567
+			\STREAM_NOTIFY_CONNECT => 'CONNECT',
568
+			\STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
569
+			\STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
570
+			\STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
571
+			\STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
572
+			\STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
573
+			\STREAM_NOTIFY_PROGRESS => 'PROGRESS',
574
+			\STREAM_NOTIFY_FAILURE => 'FAILURE',
575
+			\STREAM_NOTIFY_COMPLETED => 'COMPLETED',
576
+			\STREAM_NOTIFY_RESOLVE => 'RESOLVE',
577
+		];
578
+		static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
579
+
580
+		$value = Utils::debugResource($value);
581
+		$ident = $request->getMethod().' '.$request->getUri()->withFragment('');
582
+		self::addNotification(
583
+			$params,
584
+			static function (int $code, ...$passed) use ($ident, $value, $map, $args): void {
585
+				\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
586
+				foreach (\array_filter($passed) as $i => $v) {
587
+					\fwrite($value, $args[$i].': "'.$v.'" ');
588
+				}
589
+				\fwrite($value, "\n");
590
+			}
591
+		);
592
+	}
593
+
594
+	private static function addNotification(array &$params, callable $notify): void
595
+	{
596
+		// Wrap the existing function if needed.
597
+		if (!isset($params['notification'])) {
598
+			$params['notification'] = $notify;
599
+		} else {
600
+			$params['notification'] = self::callArray([
601
+				$params['notification'],
602
+				$notify,
603
+			]);
604
+		}
605
+	}
606
+
607
+	private static function callArray(array $functions): callable
608
+	{
609
+		return static function (...$args) use ($functions) {
610
+			foreach ($functions as $fn) {
611
+				$fn(...$args);
612
+			}
613
+		};
614
+	}
615 615
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
                     // Fix content-length header
177 177
                     if (isset($normalizedKeys['content-length'])) {
178 178
                         $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
179
-                        $length = (int) $stream->getSize();
179
+                        $length = (int)$stream->getSize();
180 180
                         if ($length === 0) {
181 181
                             unset($headers[$normalizedKeys['content-length']]);
182 182
                         } else {
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
         Psr7\Utils::copyToStream(
208 208
             $source,
209 209
             $sink,
210
-            (\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
210
+            (\strlen($contentLength) > 0 && (int)$contentLength > 0) ? (int)$contentLength : -1
211 211
         );
212 212
 
213 213
         $sink->seek(0);
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
     private function createResource(callable $callback)
229 229
     {
230 230
         $errors = [];
231
-        \set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool {
231
+        \set_error_handler(static function($_, $msg, $file, $line) use (&$errors): bool {
232 232
             $errors[] = [
233 233
                 'message' => $msg,
234 234
                 'file' => $file,
@@ -315,14 +315,14 @@  discard block
 block discarded – undo
315 315
         $uri = $this->resolveHost($request, $options);
316 316
 
317 317
         $contextResource = $this->createResource(
318
-            static function () use ($context, $params) {
318
+            static function() use ($context, $params) {
319 319
                 return \stream_context_create($context, $params);
320 320
             }
321 321
         );
322 322
 
323 323
         return $this->createResource(
324
-            function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) {
325
-                $resource = @\fopen((string) $uri, 'r', false, $contextResource);
324
+            function() use ($uri, &$http_response_header, $contextResource, $context, $options, $request) {
325
+                $resource = @\fopen((string)$uri, 'r', false, $contextResource);
326 326
                 $this->lastHeaders = $http_response_header ?? [];
327 327
 
328 328
                 if (false === $resource) {
@@ -331,7 +331,7 @@  discard block
 block discarded – undo
331 331
 
332 332
                 if (isset($options['read_timeout'])) {
333 333
                     $readTimeout = $options['read_timeout'];
334
-                    $sec = (int) $readTimeout;
334
+                    $sec = (int)$readTimeout;
335 335
                     $usec = ($readTimeout - $sec) * 100000;
336 336
                     \stream_set_timeout($resource, $sec, $usec);
337 337
                 }
@@ -389,7 +389,7 @@  discard block
 block discarded – undo
389 389
             ],
390 390
         ];
391 391
 
392
-        $body = (string) $request->getBody();
392
+        $body = (string)$request->getBody();
393 393
 
394 394
         if ('' !== $body) {
395 395
             $context['http']['content'] = $body;
@@ -544,7 +544,7 @@  discard block
 block discarded – undo
544 544
     {
545 545
         self::addNotification(
546 546
             $params,
547
-            static function ($code, $a, $b, $c, $transferred, $total) use ($value) {
547
+            static function($code, $a, $b, $c, $transferred, $total) use ($value) {
548 548
                 if ($code == \STREAM_NOTIFY_PROGRESS) {
549 549
                     // The upload progress cannot be determined. Use 0 for cURL compatibility:
550 550
                     // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
@@ -581,7 +581,7 @@  discard block
 block discarded – undo
581 581
         $ident = $request->getMethod().' '.$request->getUri()->withFragment('');
582 582
         self::addNotification(
583 583
             $params,
584
-            static function (int $code, ...$passed) use ($ident, $value, $map, $args): void {
584
+            static function(int $code, ...$passed) use ($ident, $value, $map, $args): void {
585 585
                 \fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
586 586
                 foreach (\array_filter($passed) as $i => $v) {
587 587
                     \fwrite($value, $args[$i].': "'.$v.'" ');
@@ -606,7 +606,7 @@  discard block
 block discarded – undo
606 606
 
607 607
     private static function callArray(array $functions): callable
608 608
     {
609
-        return static function (...$args) use ($functions) {
609
+        return static function(...$args) use ($functions) {
610 610
             foreach ($functions as $fn) {
611 611
                 $fn(...$args);
612 612
             }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -20,8 +20,7 @@
 block discarded – undo
20 20
  *
21 21
  * @final
22 22
  */
23
-class StreamHandler
24
-{
23
+class StreamHandler {
25 24
     /**
26 25
      * @var array
27 26
      */
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/CurlMultiHandler.php 3 patches
Indentation   +245 added lines, -245 removed lines patch added patch discarded remove patch
@@ -19,249 +19,249 @@
 block discarded – undo
19 19
  */
20 20
 class CurlMultiHandler
21 21
 {
22
-    /**
23
-     * @var CurlFactoryInterface
24
-     */
25
-    private $factory;
26
-
27
-    /**
28
-     * @var int
29
-     */
30
-    private $selectTimeout;
31
-
32
-    /**
33
-     * @var int Will be higher than 0 when `curl_multi_exec` is still running.
34
-     */
35
-    private $active = 0;
36
-
37
-    /**
38
-     * @var array Request entry handles, indexed by handle id in `addRequest`.
39
-     *
40
-     * @see CurlMultiHandler::addRequest
41
-     */
42
-    private $handles = [];
43
-
44
-    /**
45
-     * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`.
46
-     *
47
-     * @see CurlMultiHandler::addRequest
48
-     */
49
-    private $delays = [];
50
-
51
-    /**
52
-     * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt()
53
-     */
54
-    private $options = [];
55
-
56
-    /** @var resource|\CurlMultiHandle */
57
-    private $_mh;
58
-
59
-    /**
60
-     * This handler accepts the following options:
61
-     *
62
-     * - handle_factory: An optional factory  used to create curl handles
63
-     * - select_timeout: Optional timeout (in seconds) to block before timing
64
-     *   out while selecting curl handles. Defaults to 1 second.
65
-     * - options: An associative array of CURLMOPT_* options and
66
-     *   corresponding values for curl_multi_setopt()
67
-     */
68
-    public function __construct(array $options = [])
69
-    {
70
-        $this->factory = $options['handle_factory'] ?? new CurlFactory(50);
71
-
72
-        if (isset($options['select_timeout'])) {
73
-            $this->selectTimeout = $options['select_timeout'];
74
-        } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
75
-            @trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED);
76
-            $this->selectTimeout = (int) $selectTimeout;
77
-        } else {
78
-            $this->selectTimeout = 1;
79
-        }
80
-
81
-        $this->options = $options['options'] ?? [];
82
-
83
-        // unsetting the property forces the first access to go through
84
-        // __get().
85
-        unset($this->_mh);
86
-    }
87
-
88
-    /**
89
-     * @param string $name
90
-     *
91
-     * @return resource|\CurlMultiHandle
92
-     *
93
-     * @throws \BadMethodCallException when another field as `_mh` will be gotten
94
-     * @throws \RuntimeException       when curl can not initialize a multi handle
95
-     */
96
-    public function __get($name)
97
-    {
98
-        if ($name !== '_mh') {
99
-            throw new \BadMethodCallException("Can not get other property as '_mh'.");
100
-        }
101
-
102
-        $multiHandle = \curl_multi_init();
103
-
104
-        if (false === $multiHandle) {
105
-            throw new \RuntimeException('Can not initialize curl multi handle.');
106
-        }
107
-
108
-        $this->_mh = $multiHandle;
109
-
110
-        foreach ($this->options as $option => $value) {
111
-            // A warning is raised in case of a wrong option.
112
-            curl_multi_setopt($this->_mh, $option, $value);
113
-        }
114
-
115
-        return $this->_mh;
116
-    }
117
-
118
-    public function __destruct()
119
-    {
120
-        if (isset($this->_mh)) {
121
-            \curl_multi_close($this->_mh);
122
-            unset($this->_mh);
123
-        }
124
-    }
125
-
126
-    public function __invoke(RequestInterface $request, array $options): PromiseInterface
127
-    {
128
-        $easy = $this->factory->create($request, $options);
129
-        $id = (int) $easy->handle;
130
-
131
-        $promise = new Promise(
132
-            [$this, 'execute'],
133
-            function () use ($id) {
134
-                return $this->cancel($id);
135
-            }
136
-        );
137
-
138
-        $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
139
-
140
-        return $promise;
141
-    }
142
-
143
-    /**
144
-     * Ticks the curl event loop.
145
-     */
146
-    public function tick(): void
147
-    {
148
-        // Add any delayed handles if needed.
149
-        if ($this->delays) {
150
-            $currentTime = Utils::currentTime();
151
-            foreach ($this->delays as $id => $delay) {
152
-                if ($currentTime >= $delay) {
153
-                    unset($this->delays[$id]);
154
-                    \curl_multi_add_handle(
155
-                        $this->_mh,
156
-                        $this->handles[$id]['easy']->handle
157
-                    );
158
-                }
159
-            }
160
-        }
161
-
162
-        // Step through the task queue which may add additional requests.
163
-        P\Utils::queue()->run();
164
-
165
-        if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) {
166
-            // Perform a usleep if a select returns -1.
167
-            // See: https://bugs.php.net/bug.php?id=61141
168
-            \usleep(250);
169
-        }
170
-
171
-        while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
172
-        }
173
-
174
-        $this->processMessages();
175
-    }
176
-
177
-    /**
178
-     * Runs until all outstanding connections have completed.
179
-     */
180
-    public function execute(): void
181
-    {
182
-        $queue = P\Utils::queue();
183
-
184
-        while ($this->handles || !$queue->isEmpty()) {
185
-            // If there are no transfers, then sleep for the next delay
186
-            if (!$this->active && $this->delays) {
187
-                \usleep($this->timeToNext());
188
-            }
189
-            $this->tick();
190
-        }
191
-    }
192
-
193
-    private function addRequest(array $entry): void
194
-    {
195
-        $easy = $entry['easy'];
196
-        $id = (int) $easy->handle;
197
-        $this->handles[$id] = $entry;
198
-        if (empty($easy->options['delay'])) {
199
-            \curl_multi_add_handle($this->_mh, $easy->handle);
200
-        } else {
201
-            $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);
202
-        }
203
-    }
204
-
205
-    /**
206
-     * Cancels a handle from sending and removes references to it.
207
-     *
208
-     * @param int $id Handle ID to cancel and remove.
209
-     *
210
-     * @return bool True on success, false on failure.
211
-     */
212
-    private function cancel($id): bool
213
-    {
214
-        if (!is_int($id)) {
215
-            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
216
-        }
217
-
218
-        // Cannot cancel if it has been processed.
219
-        if (!isset($this->handles[$id])) {
220
-            return false;
221
-        }
222
-
223
-        $handle = $this->handles[$id]['easy']->handle;
224
-        unset($this->delays[$id], $this->handles[$id]);
225
-        \curl_multi_remove_handle($this->_mh, $handle);
226
-        \curl_close($handle);
227
-
228
-        return true;
229
-    }
230
-
231
-    private function processMessages(): void
232
-    {
233
-        while ($done = \curl_multi_info_read($this->_mh)) {
234
-            if ($done['msg'] !== \CURLMSG_DONE) {
235
-                // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216
236
-                continue;
237
-            }
238
-            $id = (int) $done['handle'];
239
-            \curl_multi_remove_handle($this->_mh, $done['handle']);
240
-
241
-            if (!isset($this->handles[$id])) {
242
-                // Probably was cancelled.
243
-                continue;
244
-            }
245
-
246
-            $entry = $this->handles[$id];
247
-            unset($this->handles[$id], $this->delays[$id]);
248
-            $entry['easy']->errno = $done['result'];
249
-            $entry['deferred']->resolve(
250
-                CurlFactory::finish($this, $entry['easy'], $this->factory)
251
-            );
252
-        }
253
-    }
254
-
255
-    private function timeToNext(): int
256
-    {
257
-        $currentTime = Utils::currentTime();
258
-        $nextTime = \PHP_INT_MAX;
259
-        foreach ($this->delays as $time) {
260
-            if ($time < $nextTime) {
261
-                $nextTime = $time;
262
-            }
263
-        }
264
-
265
-        return ((int) \max(0, $nextTime - $currentTime)) * 1000000;
266
-    }
22
+	/**
23
+	 * @var CurlFactoryInterface
24
+	 */
25
+	private $factory;
26
+
27
+	/**
28
+	 * @var int
29
+	 */
30
+	private $selectTimeout;
31
+
32
+	/**
33
+	 * @var int Will be higher than 0 when `curl_multi_exec` is still running.
34
+	 */
35
+	private $active = 0;
36
+
37
+	/**
38
+	 * @var array Request entry handles, indexed by handle id in `addRequest`.
39
+	 *
40
+	 * @see CurlMultiHandler::addRequest
41
+	 */
42
+	private $handles = [];
43
+
44
+	/**
45
+	 * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`.
46
+	 *
47
+	 * @see CurlMultiHandler::addRequest
48
+	 */
49
+	private $delays = [];
50
+
51
+	/**
52
+	 * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt()
53
+	 */
54
+	private $options = [];
55
+
56
+	/** @var resource|\CurlMultiHandle */
57
+	private $_mh;
58
+
59
+	/**
60
+	 * This handler accepts the following options:
61
+	 *
62
+	 * - handle_factory: An optional factory  used to create curl handles
63
+	 * - select_timeout: Optional timeout (in seconds) to block before timing
64
+	 *   out while selecting curl handles. Defaults to 1 second.
65
+	 * - options: An associative array of CURLMOPT_* options and
66
+	 *   corresponding values for curl_multi_setopt()
67
+	 */
68
+	public function __construct(array $options = [])
69
+	{
70
+		$this->factory = $options['handle_factory'] ?? new CurlFactory(50);
71
+
72
+		if (isset($options['select_timeout'])) {
73
+			$this->selectTimeout = $options['select_timeout'];
74
+		} elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
75
+			@trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED);
76
+			$this->selectTimeout = (int) $selectTimeout;
77
+		} else {
78
+			$this->selectTimeout = 1;
79
+		}
80
+
81
+		$this->options = $options['options'] ?? [];
82
+
83
+		// unsetting the property forces the first access to go through
84
+		// __get().
85
+		unset($this->_mh);
86
+	}
87
+
88
+	/**
89
+	 * @param string $name
90
+	 *
91
+	 * @return resource|\CurlMultiHandle
92
+	 *
93
+	 * @throws \BadMethodCallException when another field as `_mh` will be gotten
94
+	 * @throws \RuntimeException       when curl can not initialize a multi handle
95
+	 */
96
+	public function __get($name)
97
+	{
98
+		if ($name !== '_mh') {
99
+			throw new \BadMethodCallException("Can not get other property as '_mh'.");
100
+		}
101
+
102
+		$multiHandle = \curl_multi_init();
103
+
104
+		if (false === $multiHandle) {
105
+			throw new \RuntimeException('Can not initialize curl multi handle.');
106
+		}
107
+
108
+		$this->_mh = $multiHandle;
109
+
110
+		foreach ($this->options as $option => $value) {
111
+			// A warning is raised in case of a wrong option.
112
+			curl_multi_setopt($this->_mh, $option, $value);
113
+		}
114
+
115
+		return $this->_mh;
116
+	}
117
+
118
+	public function __destruct()
119
+	{
120
+		if (isset($this->_mh)) {
121
+			\curl_multi_close($this->_mh);
122
+			unset($this->_mh);
123
+		}
124
+	}
125
+
126
+	public function __invoke(RequestInterface $request, array $options): PromiseInterface
127
+	{
128
+		$easy = $this->factory->create($request, $options);
129
+		$id = (int) $easy->handle;
130
+
131
+		$promise = new Promise(
132
+			[$this, 'execute'],
133
+			function () use ($id) {
134
+				return $this->cancel($id);
135
+			}
136
+		);
137
+
138
+		$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
139
+
140
+		return $promise;
141
+	}
142
+
143
+	/**
144
+	 * Ticks the curl event loop.
145
+	 */
146
+	public function tick(): void
147
+	{
148
+		// Add any delayed handles if needed.
149
+		if ($this->delays) {
150
+			$currentTime = Utils::currentTime();
151
+			foreach ($this->delays as $id => $delay) {
152
+				if ($currentTime >= $delay) {
153
+					unset($this->delays[$id]);
154
+					\curl_multi_add_handle(
155
+						$this->_mh,
156
+						$this->handles[$id]['easy']->handle
157
+					);
158
+				}
159
+			}
160
+		}
161
+
162
+		// Step through the task queue which may add additional requests.
163
+		P\Utils::queue()->run();
164
+
165
+		if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) {
166
+			// Perform a usleep if a select returns -1.
167
+			// See: https://bugs.php.net/bug.php?id=61141
168
+			\usleep(250);
169
+		}
170
+
171
+		while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
172
+		}
173
+
174
+		$this->processMessages();
175
+	}
176
+
177
+	/**
178
+	 * Runs until all outstanding connections have completed.
179
+	 */
180
+	public function execute(): void
181
+	{
182
+		$queue = P\Utils::queue();
183
+
184
+		while ($this->handles || !$queue->isEmpty()) {
185
+			// If there are no transfers, then sleep for the next delay
186
+			if (!$this->active && $this->delays) {
187
+				\usleep($this->timeToNext());
188
+			}
189
+			$this->tick();
190
+		}
191
+	}
192
+
193
+	private function addRequest(array $entry): void
194
+	{
195
+		$easy = $entry['easy'];
196
+		$id = (int) $easy->handle;
197
+		$this->handles[$id] = $entry;
198
+		if (empty($easy->options['delay'])) {
199
+			\curl_multi_add_handle($this->_mh, $easy->handle);
200
+		} else {
201
+			$this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);
202
+		}
203
+	}
204
+
205
+	/**
206
+	 * Cancels a handle from sending and removes references to it.
207
+	 *
208
+	 * @param int $id Handle ID to cancel and remove.
209
+	 *
210
+	 * @return bool True on success, false on failure.
211
+	 */
212
+	private function cancel($id): bool
213
+	{
214
+		if (!is_int($id)) {
215
+			trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
216
+		}
217
+
218
+		// Cannot cancel if it has been processed.
219
+		if (!isset($this->handles[$id])) {
220
+			return false;
221
+		}
222
+
223
+		$handle = $this->handles[$id]['easy']->handle;
224
+		unset($this->delays[$id], $this->handles[$id]);
225
+		\curl_multi_remove_handle($this->_mh, $handle);
226
+		\curl_close($handle);
227
+
228
+		return true;
229
+	}
230
+
231
+	private function processMessages(): void
232
+	{
233
+		while ($done = \curl_multi_info_read($this->_mh)) {
234
+			if ($done['msg'] !== \CURLMSG_DONE) {
235
+				// if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216
236
+				continue;
237
+			}
238
+			$id = (int) $done['handle'];
239
+			\curl_multi_remove_handle($this->_mh, $done['handle']);
240
+
241
+			if (!isset($this->handles[$id])) {
242
+				// Probably was cancelled.
243
+				continue;
244
+			}
245
+
246
+			$entry = $this->handles[$id];
247
+			unset($this->handles[$id], $this->delays[$id]);
248
+			$entry['easy']->errno = $done['result'];
249
+			$entry['deferred']->resolve(
250
+				CurlFactory::finish($this, $entry['easy'], $this->factory)
251
+			);
252
+		}
253
+	}
254
+
255
+	private function timeToNext(): int
256
+	{
257
+		$currentTime = Utils::currentTime();
258
+		$nextTime = \PHP_INT_MAX;
259
+		foreach ($this->delays as $time) {
260
+			if ($time < $nextTime) {
261
+				$nextTime = $time;
262
+			}
263
+		}
264
+
265
+		return ((int) \max(0, $nextTime - $currentTime)) * 1000000;
266
+	}
267 267
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
             $this->selectTimeout = $options['select_timeout'];
74 74
         } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
75 75
             @trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED);
76
-            $this->selectTimeout = (int) $selectTimeout;
76
+            $this->selectTimeout = (int)$selectTimeout;
77 77
         } else {
78 78
             $this->selectTimeout = 1;
79 79
         }
@@ -126,11 +126,11 @@  discard block
 block discarded – undo
126 126
     public function __invoke(RequestInterface $request, array $options): PromiseInterface
127 127
     {
128 128
         $easy = $this->factory->create($request, $options);
129
-        $id = (int) $easy->handle;
129
+        $id = (int)$easy->handle;
130 130
 
131 131
         $promise = new Promise(
132 132
             [$this, 'execute'],
133
-            function () use ($id) {
133
+            function() use ($id) {
134 134
                 return $this->cancel($id);
135 135
             }
136 136
         );
@@ -193,7 +193,7 @@  discard block
 block discarded – undo
193 193
     private function addRequest(array $entry): void
194 194
     {
195 195
         $easy = $entry['easy'];
196
-        $id = (int) $easy->handle;
196
+        $id = (int)$easy->handle;
197 197
         $this->handles[$id] = $entry;
198 198
         if (empty($easy->options['delay'])) {
199 199
             \curl_multi_add_handle($this->_mh, $easy->handle);
@@ -235,7 +235,7 @@  discard block
 block discarded – undo
235 235
                 // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216
236 236
                 continue;
237 237
             }
238
-            $id = (int) $done['handle'];
238
+            $id = (int)$done['handle'];
239 239
             \curl_multi_remove_handle($this->_mh, $done['handle']);
240 240
 
241 241
             if (!isset($this->handles[$id])) {
@@ -262,6 +262,6 @@  discard block
 block discarded – undo
262 262
             }
263 263
         }
264 264
 
265
-        return ((int) \max(0, $nextTime - $currentTime)) * 1000000;
265
+        return ((int)\max(0, $nextTime - $currentTime)) * 1000000;
266 266
     }
267 267
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -17,8 +17,7 @@
 block discarded – undo
17 17
  *
18 18
  * @final
19 19
  */
20
-class CurlMultiHandler
21
-{
20
+class CurlMultiHandler {
22 21
     /**
23 22
      * @var CurlFactoryInterface
24 23
      */
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/HeaderProcessor.php 3 patches
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -9,34 +9,34 @@
 block discarded – undo
9 9
  */
10 10
 final class HeaderProcessor
11 11
 {
12
-    /**
13
-     * Returns the HTTP version, status code, reason phrase, and headers.
14
-     *
15
-     * @param string[] $headers
16
-     *
17
-     * @return array{0:string, 1:int, 2:?string, 3:array}
18
-     *
19
-     * @throws \RuntimeException
20
-     */
21
-    public static function parseHeaders(array $headers): array
22
-    {
23
-        if ($headers === []) {
24
-            throw new \RuntimeException('Expected a non-empty array of header data');
25
-        }
26
-
27
-        $parts = \explode(' ', \array_shift($headers), 3);
28
-        $version = \explode('/', $parts[0])[1] ?? null;
29
-
30
-        if ($version === null) {
31
-            throw new \RuntimeException('HTTP version missing from header data');
32
-        }
33
-
34
-        $status = $parts[1] ?? null;
35
-
36
-        if ($status === null) {
37
-            throw new \RuntimeException('HTTP status code missing from header data');
38
-        }
39
-
40
-        return [$version, (int) $status, $parts[2] ?? null, Utils::headersFromLines($headers)];
41
-    }
12
+	/**
13
+	 * Returns the HTTP version, status code, reason phrase, and headers.
14
+	 *
15
+	 * @param string[] $headers
16
+	 *
17
+	 * @return array{0:string, 1:int, 2:?string, 3:array}
18
+	 *
19
+	 * @throws \RuntimeException
20
+	 */
21
+	public static function parseHeaders(array $headers): array
22
+	{
23
+		if ($headers === []) {
24
+			throw new \RuntimeException('Expected a non-empty array of header data');
25
+		}
26
+
27
+		$parts = \explode(' ', \array_shift($headers), 3);
28
+		$version = \explode('/', $parts[0])[1] ?? null;
29
+
30
+		if ($version === null) {
31
+			throw new \RuntimeException('HTTP version missing from header data');
32
+		}
33
+
34
+		$status = $parts[1] ?? null;
35
+
36
+		if ($status === null) {
37
+			throw new \RuntimeException('HTTP status code missing from header data');
38
+		}
39
+
40
+		return [$version, (int) $status, $parts[2] ?? null, Utils::headersFromLines($headers)];
41
+	}
42 42
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -37,6 +37,6 @@
 block discarded – undo
37 37
             throw new \RuntimeException('HTTP status code missing from header data');
38 38
         }
39 39
 
40
-        return [$version, (int) $status, $parts[2] ?? null, Utils::headersFromLines($headers)];
40
+        return [$version, (int)$status, $parts[2] ?? null, Utils::headersFromLines($headers)];
41 41
     }
42 42
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -7,8 +7,7 @@
 block discarded – undo
7 7
 /**
8 8
  * @internal
9 9
  */
10
-final class HeaderProcessor
11
-{
10
+final class HeaderProcessor {
12 11
     /**
13 12
      * Returns the HTTP version, status code, reason phrase, and headers.
14 13
      *
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/MockHandler.php 2 patches
Indentation   +190 added lines, -190 removed lines patch added patch discarded remove patch
@@ -19,194 +19,194 @@
 block discarded – undo
19 19
  */
20 20
 class MockHandler implements \Countable
21 21
 {
22
-    /**
23
-     * @var array
24
-     */
25
-    private $queue = [];
26
-
27
-    /**
28
-     * @var RequestInterface|null
29
-     */
30
-    private $lastRequest;
31
-
32
-    /**
33
-     * @var array
34
-     */
35
-    private $lastOptions = [];
36
-
37
-    /**
38
-     * @var callable|null
39
-     */
40
-    private $onFulfilled;
41
-
42
-    /**
43
-     * @var callable|null
44
-     */
45
-    private $onRejected;
46
-
47
-    /**
48
-     * Creates a new MockHandler that uses the default handler stack list of
49
-     * middlewares.
50
-     *
51
-     * @param array|null    $queue       Array of responses, callables, or exceptions.
52
-     * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
53
-     * @param callable|null $onRejected  Callback to invoke when the return value is rejected.
54
-     */
55
-    public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack
56
-    {
57
-        return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
58
-    }
59
-
60
-    /**
61
-     * The passed in value must be an array of
62
-     * {@see \OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\ResponseInterface} objects, Exceptions,
63
-     * callables, or Promises.
64
-     *
65
-     * @param array<int, mixed>|null $queue       The parameters to be passed to the append function, as an indexed array.
66
-     * @param callable|null          $onFulfilled Callback to invoke when the return value is fulfilled.
67
-     * @param callable|null          $onRejected  Callback to invoke when the return value is rejected.
68
-     */
69
-    public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null)
70
-    {
71
-        $this->onFulfilled = $onFulfilled;
72
-        $this->onRejected = $onRejected;
73
-
74
-        if ($queue) {
75
-            // array_values included for BC
76
-            $this->append(...array_values($queue));
77
-        }
78
-    }
79
-
80
-    public function __invoke(RequestInterface $request, array $options): PromiseInterface
81
-    {
82
-        if (!$this->queue) {
83
-            throw new \OutOfBoundsException('Mock queue is empty');
84
-        }
85
-
86
-        if (isset($options['delay']) && \is_numeric($options['delay'])) {
87
-            \usleep((int) $options['delay'] * 1000);
88
-        }
89
-
90
-        $this->lastRequest = $request;
91
-        $this->lastOptions = $options;
92
-        $response = \array_shift($this->queue);
93
-
94
-        if (isset($options['on_headers'])) {
95
-            if (!\is_callable($options['on_headers'])) {
96
-                throw new \InvalidArgumentException('on_headers must be callable');
97
-            }
98
-            try {
99
-                $options['on_headers']($response);
100
-            } catch (\Exception $e) {
101
-                $msg = 'An error was encountered during the on_headers event';
102
-                $response = new RequestException($msg, $request, $response, $e);
103
-            }
104
-        }
105
-
106
-        if (\is_callable($response)) {
107
-            $response = $response($request, $options);
108
-        }
109
-
110
-        $response = $response instanceof \Throwable
111
-            ? P\Create::rejectionFor($response)
112
-            : P\Create::promiseFor($response);
113
-
114
-        return $response->then(
115
-            function (?ResponseInterface $value) use ($request, $options) {
116
-                $this->invokeStats($request, $options, $value);
117
-                if ($this->onFulfilled) {
118
-                    ($this->onFulfilled)($value);
119
-                }
120
-
121
-                if ($value !== null && isset($options['sink'])) {
122
-                    $contents = (string) $value->getBody();
123
-                    $sink = $options['sink'];
124
-
125
-                    if (\is_resource($sink)) {
126
-                        \fwrite($sink, $contents);
127
-                    } elseif (\is_string($sink)) {
128
-                        \file_put_contents($sink, $contents);
129
-                    } elseif ($sink instanceof StreamInterface) {
130
-                        $sink->write($contents);
131
-                    }
132
-                }
133
-
134
-                return $value;
135
-            },
136
-            function ($reason) use ($request, $options) {
137
-                $this->invokeStats($request, $options, null, $reason);
138
-                if ($this->onRejected) {
139
-                    ($this->onRejected)($reason);
140
-                }
141
-
142
-                return P\Create::rejectionFor($reason);
143
-            }
144
-        );
145
-    }
146
-
147
-    /**
148
-     * Adds one or more variadic requests, exceptions, callables, or promises
149
-     * to the queue.
150
-     *
151
-     * @param mixed ...$values
152
-     */
153
-    public function append(...$values): void
154
-    {
155
-        foreach ($values as $value) {
156
-            if ($value instanceof ResponseInterface
157
-                || $value instanceof \Throwable
158
-                || $value instanceof PromiseInterface
159
-                || \is_callable($value)
160
-            ) {
161
-                $this->queue[] = $value;
162
-            } else {
163
-                throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.Utils::describeType($value));
164
-            }
165
-        }
166
-    }
167
-
168
-    /**
169
-     * Get the last received request.
170
-     */
171
-    public function getLastRequest(): ?RequestInterface
172
-    {
173
-        return $this->lastRequest;
174
-    }
175
-
176
-    /**
177
-     * Get the last received request options.
178
-     */
179
-    public function getLastOptions(): array
180
-    {
181
-        return $this->lastOptions;
182
-    }
183
-
184
-    /**
185
-     * Returns the number of remaining items in the queue.
186
-     */
187
-    public function count(): int
188
-    {
189
-        return \count($this->queue);
190
-    }
191
-
192
-    public function reset(): void
193
-    {
194
-        $this->queue = [];
195
-    }
196
-
197
-    /**
198
-     * @param mixed $reason Promise or reason.
199
-     */
200
-    private function invokeStats(
201
-        RequestInterface $request,
202
-        array $options,
203
-        ResponseInterface $response = null,
204
-        $reason = null
205
-    ): void {
206
-        if (isset($options['on_stats'])) {
207
-            $transferTime = $options['transfer_time'] ?? 0;
208
-            $stats = new TransferStats($request, $response, $transferTime, $reason);
209
-            ($options['on_stats'])($stats);
210
-        }
211
-    }
22
+	/**
23
+	 * @var array
24
+	 */
25
+	private $queue = [];
26
+
27
+	/**
28
+	 * @var RequestInterface|null
29
+	 */
30
+	private $lastRequest;
31
+
32
+	/**
33
+	 * @var array
34
+	 */
35
+	private $lastOptions = [];
36
+
37
+	/**
38
+	 * @var callable|null
39
+	 */
40
+	private $onFulfilled;
41
+
42
+	/**
43
+	 * @var callable|null
44
+	 */
45
+	private $onRejected;
46
+
47
+	/**
48
+	 * Creates a new MockHandler that uses the default handler stack list of
49
+	 * middlewares.
50
+	 *
51
+	 * @param array|null    $queue       Array of responses, callables, or exceptions.
52
+	 * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
53
+	 * @param callable|null $onRejected  Callback to invoke when the return value is rejected.
54
+	 */
55
+	public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack
56
+	{
57
+		return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
58
+	}
59
+
60
+	/**
61
+	 * The passed in value must be an array of
62
+	 * {@see \OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\ResponseInterface} objects, Exceptions,
63
+	 * callables, or Promises.
64
+	 *
65
+	 * @param array<int, mixed>|null $queue       The parameters to be passed to the append function, as an indexed array.
66
+	 * @param callable|null          $onFulfilled Callback to invoke when the return value is fulfilled.
67
+	 * @param callable|null          $onRejected  Callback to invoke when the return value is rejected.
68
+	 */
69
+	public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null)
70
+	{
71
+		$this->onFulfilled = $onFulfilled;
72
+		$this->onRejected = $onRejected;
73
+
74
+		if ($queue) {
75
+			// array_values included for BC
76
+			$this->append(...array_values($queue));
77
+		}
78
+	}
79
+
80
+	public function __invoke(RequestInterface $request, array $options): PromiseInterface
81
+	{
82
+		if (!$this->queue) {
83
+			throw new \OutOfBoundsException('Mock queue is empty');
84
+		}
85
+
86
+		if (isset($options['delay']) && \is_numeric($options['delay'])) {
87
+			\usleep((int) $options['delay'] * 1000);
88
+		}
89
+
90
+		$this->lastRequest = $request;
91
+		$this->lastOptions = $options;
92
+		$response = \array_shift($this->queue);
93
+
94
+		if (isset($options['on_headers'])) {
95
+			if (!\is_callable($options['on_headers'])) {
96
+				throw new \InvalidArgumentException('on_headers must be callable');
97
+			}
98
+			try {
99
+				$options['on_headers']($response);
100
+			} catch (\Exception $e) {
101
+				$msg = 'An error was encountered during the on_headers event';
102
+				$response = new RequestException($msg, $request, $response, $e);
103
+			}
104
+		}
105
+
106
+		if (\is_callable($response)) {
107
+			$response = $response($request, $options);
108
+		}
109
+
110
+		$response = $response instanceof \Throwable
111
+			? P\Create::rejectionFor($response)
112
+			: P\Create::promiseFor($response);
113
+
114
+		return $response->then(
115
+			function (?ResponseInterface $value) use ($request, $options) {
116
+				$this->invokeStats($request, $options, $value);
117
+				if ($this->onFulfilled) {
118
+					($this->onFulfilled)($value);
119
+				}
120
+
121
+				if ($value !== null && isset($options['sink'])) {
122
+					$contents = (string) $value->getBody();
123
+					$sink = $options['sink'];
124
+
125
+					if (\is_resource($sink)) {
126
+						\fwrite($sink, $contents);
127
+					} elseif (\is_string($sink)) {
128
+						\file_put_contents($sink, $contents);
129
+					} elseif ($sink instanceof StreamInterface) {
130
+						$sink->write($contents);
131
+					}
132
+				}
133
+
134
+				return $value;
135
+			},
136
+			function ($reason) use ($request, $options) {
137
+				$this->invokeStats($request, $options, null, $reason);
138
+				if ($this->onRejected) {
139
+					($this->onRejected)($reason);
140
+				}
141
+
142
+				return P\Create::rejectionFor($reason);
143
+			}
144
+		);
145
+	}
146
+
147
+	/**
148
+	 * Adds one or more variadic requests, exceptions, callables, or promises
149
+	 * to the queue.
150
+	 *
151
+	 * @param mixed ...$values
152
+	 */
153
+	public function append(...$values): void
154
+	{
155
+		foreach ($values as $value) {
156
+			if ($value instanceof ResponseInterface
157
+				|| $value instanceof \Throwable
158
+				|| $value instanceof PromiseInterface
159
+				|| \is_callable($value)
160
+			) {
161
+				$this->queue[] = $value;
162
+			} else {
163
+				throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.Utils::describeType($value));
164
+			}
165
+		}
166
+	}
167
+
168
+	/**
169
+	 * Get the last received request.
170
+	 */
171
+	public function getLastRequest(): ?RequestInterface
172
+	{
173
+		return $this->lastRequest;
174
+	}
175
+
176
+	/**
177
+	 * Get the last received request options.
178
+	 */
179
+	public function getLastOptions(): array
180
+	{
181
+		return $this->lastOptions;
182
+	}
183
+
184
+	/**
185
+	 * Returns the number of remaining items in the queue.
186
+	 */
187
+	public function count(): int
188
+	{
189
+		return \count($this->queue);
190
+	}
191
+
192
+	public function reset(): void
193
+	{
194
+		$this->queue = [];
195
+	}
196
+
197
+	/**
198
+	 * @param mixed $reason Promise or reason.
199
+	 */
200
+	private function invokeStats(
201
+		RequestInterface $request,
202
+		array $options,
203
+		ResponseInterface $response = null,
204
+		$reason = null
205
+	): void {
206
+		if (isset($options['on_stats'])) {
207
+			$transferTime = $options['transfer_time'] ?? 0;
208
+			$stats = new TransferStats($request, $response, $transferTime, $reason);
209
+			($options['on_stats'])($stats);
210
+		}
211
+	}
212 212
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
         }
85 85
 
86 86
         if (isset($options['delay']) && \is_numeric($options['delay'])) {
87
-            \usleep((int) $options['delay'] * 1000);
87
+            \usleep((int)$options['delay'] * 1000);
88 88
         }
89 89
 
90 90
         $this->lastRequest = $request;
@@ -112,14 +112,14 @@  discard block
 block discarded – undo
112 112
             : P\Create::promiseFor($response);
113 113
 
114 114
         return $response->then(
115
-            function (?ResponseInterface $value) use ($request, $options) {
115
+            function(?ResponseInterface $value) use ($request, $options) {
116 116
                 $this->invokeStats($request, $options, $value);
117 117
                 if ($this->onFulfilled) {
118 118
                     ($this->onFulfilled)($value);
119 119
                 }
120 120
 
121 121
                 if ($value !== null && isset($options['sink'])) {
122
-                    $contents = (string) $value->getBody();
122
+                    $contents = (string)$value->getBody();
123 123
                     $sink = $options['sink'];
124 124
 
125 125
                     if (\is_resource($sink)) {
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
 
134 134
                 return $value;
135 135
             },
136
-            function ($reason) use ($request, $options) {
136
+            function($reason) use ($request, $options) {
137 137
                 $this->invokeStats($request, $options, null, $reason);
138 138
                 if ($this->onRejected) {
139 139
                     ($this->onRejected)($reason);
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/EasyHandle.php 3 patches
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -15,98 +15,98 @@
 block discarded – undo
15 15
  */
16 16
 final class EasyHandle
17 17
 {
18
-    /**
19
-     * @var resource|\CurlHandle cURL resource
20
-     */
21
-    public $handle;
22
-
23
-    /**
24
-     * @var StreamInterface Where data is being written
25
-     */
26
-    public $sink;
27
-
28
-    /**
29
-     * @var array Received HTTP headers so far
30
-     */
31
-    public $headers = [];
32
-
33
-    /**
34
-     * @var ResponseInterface|null Received response (if any)
35
-     */
36
-    public $response;
37
-
38
-    /**
39
-     * @var RequestInterface Request being sent
40
-     */
41
-    public $request;
42
-
43
-    /**
44
-     * @var array Request options
45
-     */
46
-    public $options = [];
47
-
48
-    /**
49
-     * @var int cURL error number (if any)
50
-     */
51
-    public $errno = 0;
52
-
53
-    /**
54
-     * @var \Throwable|null Exception during on_headers (if any)
55
-     */
56
-    public $onHeadersException;
57
-
58
-    /**
59
-     * @var \Exception|null Exception during createResponse (if any)
60
-     */
61
-    public $createResponseException;
62
-
63
-    /**
64
-     * Attach a response to the easy handle based on the received headers.
65
-     *
66
-     * @throws \RuntimeException if no headers have been received or the first
67
-     *                           header line is invalid.
68
-     */
69
-    public function createResponse(): void
70
-    {
71
-        [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($this->headers);
72
-
73
-        $normalizedKeys = Utils::normalizeHeaderKeys($headers);
74
-
75
-        if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) {
76
-            $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
77
-            unset($headers[$normalizedKeys['content-encoding']]);
78
-            if (isset($normalizedKeys['content-length'])) {
79
-                $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
80
-
81
-                $bodyLength = (int) $this->sink->getSize();
82
-                if ($bodyLength) {
83
-                    $headers[$normalizedKeys['content-length']] = $bodyLength;
84
-                } else {
85
-                    unset($headers[$normalizedKeys['content-length']]);
86
-                }
87
-            }
88
-        }
89
-
90
-        // Attach a response to the easy handle with the parsed headers.
91
-        $this->response = new Response(
92
-            $status,
93
-            $headers,
94
-            $this->sink,
95
-            $ver,
96
-            $reason
97
-        );
98
-    }
99
-
100
-    /**
101
-     * @param string $name
102
-     *
103
-     * @return void
104
-     *
105
-     * @throws \BadMethodCallException
106
-     */
107
-    public function __get($name)
108
-    {
109
-        $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name;
110
-        throw new \BadMethodCallException($msg);
111
-    }
18
+	/**
19
+	 * @var resource|\CurlHandle cURL resource
20
+	 */
21
+	public $handle;
22
+
23
+	/**
24
+	 * @var StreamInterface Where data is being written
25
+	 */
26
+	public $sink;
27
+
28
+	/**
29
+	 * @var array Received HTTP headers so far
30
+	 */
31
+	public $headers = [];
32
+
33
+	/**
34
+	 * @var ResponseInterface|null Received response (if any)
35
+	 */
36
+	public $response;
37
+
38
+	/**
39
+	 * @var RequestInterface Request being sent
40
+	 */
41
+	public $request;
42
+
43
+	/**
44
+	 * @var array Request options
45
+	 */
46
+	public $options = [];
47
+
48
+	/**
49
+	 * @var int cURL error number (if any)
50
+	 */
51
+	public $errno = 0;
52
+
53
+	/**
54
+	 * @var \Throwable|null Exception during on_headers (if any)
55
+	 */
56
+	public $onHeadersException;
57
+
58
+	/**
59
+	 * @var \Exception|null Exception during createResponse (if any)
60
+	 */
61
+	public $createResponseException;
62
+
63
+	/**
64
+	 * Attach a response to the easy handle based on the received headers.
65
+	 *
66
+	 * @throws \RuntimeException if no headers have been received or the first
67
+	 *                           header line is invalid.
68
+	 */
69
+	public function createResponse(): void
70
+	{
71
+		[$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($this->headers);
72
+
73
+		$normalizedKeys = Utils::normalizeHeaderKeys($headers);
74
+
75
+		if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) {
76
+			$headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
77
+			unset($headers[$normalizedKeys['content-encoding']]);
78
+			if (isset($normalizedKeys['content-length'])) {
79
+				$headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
80
+
81
+				$bodyLength = (int) $this->sink->getSize();
82
+				if ($bodyLength) {
83
+					$headers[$normalizedKeys['content-length']] = $bodyLength;
84
+				} else {
85
+					unset($headers[$normalizedKeys['content-length']]);
86
+				}
87
+			}
88
+		}
89
+
90
+		// Attach a response to the easy handle with the parsed headers.
91
+		$this->response = new Response(
92
+			$status,
93
+			$headers,
94
+			$this->sink,
95
+			$ver,
96
+			$reason
97
+		);
98
+	}
99
+
100
+	/**
101
+	 * @param string $name
102
+	 *
103
+	 * @return void
104
+	 *
105
+	 * @throws \BadMethodCallException
106
+	 */
107
+	public function __get($name)
108
+	{
109
+		$msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name;
110
+		throw new \BadMethodCallException($msg);
111
+	}
112 112
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@
 block discarded – undo
78 78
             if (isset($normalizedKeys['content-length'])) {
79 79
                 $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
80 80
 
81
-                $bodyLength = (int) $this->sink->getSize();
81
+                $bodyLength = (int)$this->sink->getSize();
82 82
                 if ($bodyLength) {
83 83
                     $headers[$normalizedKeys['content-length']] = $bodyLength;
84 84
                 } else {
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -13,8 +13,7 @@
 block discarded – undo
13 13
  *
14 14
  * @internal
15 15
  */
16
-final class EasyHandle
17
-{
16
+final class EasyHandle {
18 17
     /**
19 18
      * @var resource|\CurlHandle cURL resource
20 19
      */
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/Proxy.php 3 patches
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -13,39 +13,39 @@
 block discarded – undo
13 13
  */
14 14
 class Proxy
15 15
 {
16
-    /**
17
-     * Sends synchronous requests to a specific handler while sending all other
18
-     * requests to another handler.
19
-     *
20
-     * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses
21
-     * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $sync    Handler used for synchronous responses.
22
-     *
23
-     * @return callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface Returns the composed handler.
24
-     */
25
-    public static function wrapSync(callable $default, callable $sync): callable
26
-    {
27
-        return static function (RequestInterface $request, array $options) use ($default, $sync): PromiseInterface {
28
-            return empty($options[RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options);
29
-        };
30
-    }
16
+	/**
17
+	 * Sends synchronous requests to a specific handler while sending all other
18
+	 * requests to another handler.
19
+	 *
20
+	 * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses
21
+	 * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $sync    Handler used for synchronous responses.
22
+	 *
23
+	 * @return callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface Returns the composed handler.
24
+	 */
25
+	public static function wrapSync(callable $default, callable $sync): callable
26
+	{
27
+		return static function (RequestInterface $request, array $options) use ($default, $sync): PromiseInterface {
28
+			return empty($options[RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options);
29
+		};
30
+	}
31 31
 
32
-    /**
33
-     * Sends streaming requests to a streaming compatible handler while sending
34
-     * all other requests to a default handler.
35
-     *
36
-     * This, for example, could be useful for taking advantage of the
37
-     * performance benefits of curl while still supporting true streaming
38
-     * through the StreamHandler.
39
-     *
40
-     * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $default   Handler used for non-streaming responses
41
-     * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses
42
-     *
43
-     * @return callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface Returns the composed handler.
44
-     */
45
-    public static function wrapStreaming(callable $default, callable $streaming): callable
46
-    {
47
-        return static function (RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface {
48
-            return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options);
49
-        };
50
-    }
32
+	/**
33
+	 * Sends streaming requests to a streaming compatible handler while sending
34
+	 * all other requests to a default handler.
35
+	 *
36
+	 * This, for example, could be useful for taking advantage of the
37
+	 * performance benefits of curl while still supporting true streaming
38
+	 * through the StreamHandler.
39
+	 *
40
+	 * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $default   Handler used for non-streaming responses
41
+	 * @param callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses
42
+	 *
43
+	 * @return callable(\OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface, array): \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise\PromiseInterface Returns the composed handler.
44
+	 */
45
+	public static function wrapStreaming(callable $default, callable $streaming): callable
46
+	{
47
+		return static function (RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface {
48
+			return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options);
49
+		};
50
+	}
51 51
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
      */
25 25
     public static function wrapSync(callable $default, callable $sync): callable
26 26
     {
27
-        return static function (RequestInterface $request, array $options) use ($default, $sync): PromiseInterface {
27
+        return static function(RequestInterface $request, array $options) use ($default, $sync): PromiseInterface {
28 28
             return empty($options[RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options);
29 29
         };
30 30
     }
@@ -44,7 +44,7 @@  discard block
 block discarded – undo
44 44
      */
45 45
     public static function wrapStreaming(callable $default, callable $streaming): callable
46 46
     {
47
-        return static function (RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface {
47
+        return static function(RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface {
48 48
             return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options);
49 49
         };
50 50
     }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -11,8 +11,7 @@
 block discarded – undo
11 11
  *
12 12
  * @final
13 13
  */
14
-class Proxy
15
-{
14
+class Proxy {
16 15
     /**
17 16
      * Sends synchronous requests to a specific handler while sending all other
18 17
      * requests to another handler.
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/CurlFactoryInterface.php 2 patches
Indentation   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -6,20 +6,20 @@
 block discarded – undo
6 6
 
7 7
 interface CurlFactoryInterface
8 8
 {
9
-    /**
10
-     * Creates a cURL handle resource.
11
-     *
12
-     * @param RequestInterface $request Request
13
-     * @param array            $options Transfer options
14
-     *
15
-     * @throws \RuntimeException when an option cannot be applied
16
-     */
17
-    public function create(RequestInterface $request, array $options): EasyHandle;
9
+	/**
10
+	 * Creates a cURL handle resource.
11
+	 *
12
+	 * @param RequestInterface $request Request
13
+	 * @param array            $options Transfer options
14
+	 *
15
+	 * @throws \RuntimeException when an option cannot be applied
16
+	 */
17
+	public function create(RequestInterface $request, array $options): EasyHandle;
18 18
 
19
-    /**
20
-     * Release an easy handle, allowing it to be reused or closed.
21
-     *
22
-     * This function must call unset on the easy handle's "handle" property.
23
-     */
24
-    public function release(EasyHandle $easy): void;
19
+	/**
20
+	 * Release an easy handle, allowing it to be reused or closed.
21
+	 *
22
+	 * This function must call unset on the easy handle's "handle" property.
23
+	 */
24
+	public function release(EasyHandle $easy): void;
25 25
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -4,8 +4,7 @@
 block discarded – undo
4 4
 
5 5
 use OCA\FullTextSearch_Elasticsearch\Vendor\Psr\Http\Message\RequestInterface;
6 6
 
7
-interface CurlFactoryInterface
8
-{
7
+interface CurlFactoryInterface {
9 8
     /**
10 9
      * Creates a cURL handle resource.
11 10
      *
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/CurlFactory.php 3 patches
Indentation   +616 added lines, -616 removed lines patch added patch discarded remove patch
@@ -19,620 +19,620 @@
 block discarded – undo
19 19
  */
20 20
 class CurlFactory implements CurlFactoryInterface
21 21
 {
22
-    public const CURL_VERSION_STR = 'curl_version';
23
-
24
-    /**
25
-     * @deprecated
26
-     */
27
-    public const LOW_CURL_VERSION_NUMBER = '7.21.2';
28
-
29
-    /**
30
-     * @var resource[]|\CurlHandle[]
31
-     */
32
-    private $handles = [];
33
-
34
-    /**
35
-     * @var int Total number of idle handles to keep in cache
36
-     */
37
-    private $maxHandles;
38
-
39
-    /**
40
-     * @param int $maxHandles Maximum number of idle handles.
41
-     */
42
-    public function __construct(int $maxHandles)
43
-    {
44
-        $this->maxHandles = $maxHandles;
45
-    }
46
-
47
-    public function create(RequestInterface $request, array $options): EasyHandle
48
-    {
49
-        if (isset($options['curl']['body_as_string'])) {
50
-            $options['_body_as_string'] = $options['curl']['body_as_string'];
51
-            unset($options['curl']['body_as_string']);
52
-        }
53
-
54
-        $easy = new EasyHandle();
55
-        $easy->request = $request;
56
-        $easy->options = $options;
57
-        $conf = $this->getDefaultConf($easy);
58
-        $this->applyMethod($easy, $conf);
59
-        $this->applyHandlerOptions($easy, $conf);
60
-        $this->applyHeaders($easy, $conf);
61
-        unset($conf['_headers']);
62
-
63
-        // Add handler options from the request configuration options
64
-        if (isset($options['curl'])) {
65
-            $conf = \array_replace($conf, $options['curl']);
66
-        }
67
-
68
-        $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
69
-        $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init();
70
-        curl_setopt_array($easy->handle, $conf);
71
-
72
-        return $easy;
73
-    }
74
-
75
-    public function release(EasyHandle $easy): void
76
-    {
77
-        $resource = $easy->handle;
78
-        unset($easy->handle);
79
-
80
-        if (\count($this->handles) >= $this->maxHandles) {
81
-            \curl_close($resource);
82
-        } else {
83
-            // Remove all callback functions as they can hold onto references
84
-            // and are not cleaned up by curl_reset. Using curl_setopt_array
85
-            // does not work for some reason, so removing each one
86
-            // individually.
87
-            \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null);
88
-            \curl_setopt($resource, \CURLOPT_READFUNCTION, null);
89
-            \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null);
90
-            \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null);
91
-            \curl_reset($resource);
92
-            $this->handles[] = $resource;
93
-        }
94
-    }
95
-
96
-    /**
97
-     * Completes a cURL transaction, either returning a response promise or a
98
-     * rejected promise.
99
-     *
100
-     * @param callable(RequestInterface, array): PromiseInterface $handler
101
-     * @param CurlFactoryInterface                                $factory Dictates how the handle is released
102
-     */
103
-    public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface
104
-    {
105
-        if (isset($easy->options['on_stats'])) {
106
-            self::invokeStats($easy);
107
-        }
108
-
109
-        if (!$easy->response || $easy->errno) {
110
-            return self::finishError($handler, $easy, $factory);
111
-        }
112
-
113
-        // Return the response if it is present and there is no error.
114
-        $factory->release($easy);
115
-
116
-        // Rewind the body of the response if possible.
117
-        $body = $easy->response->getBody();
118
-        if ($body->isSeekable()) {
119
-            $body->rewind();
120
-        }
121
-
122
-        return new FulfilledPromise($easy->response);
123
-    }
124
-
125
-    private static function invokeStats(EasyHandle $easy): void
126
-    {
127
-        $curlStats = \curl_getinfo($easy->handle);
128
-        $curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME);
129
-        $stats = new TransferStats(
130
-            $easy->request,
131
-            $easy->response,
132
-            $curlStats['total_time'],
133
-            $easy->errno,
134
-            $curlStats
135
-        );
136
-        ($easy->options['on_stats'])($stats);
137
-    }
138
-
139
-    /**
140
-     * @param callable(RequestInterface, array): PromiseInterface $handler
141
-     */
142
-    private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface
143
-    {
144
-        // Get error information and release the handle to the factory.
145
-        $ctx = [
146
-            'errno' => $easy->errno,
147
-            'error' => \curl_error($easy->handle),
148
-            'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME),
149
-        ] + \curl_getinfo($easy->handle);
150
-        $ctx[self::CURL_VERSION_STR] = \curl_version()['version'];
151
-        $factory->release($easy);
152
-
153
-        // Retry when nothing is present or when curl failed to rewind.
154
-        if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) {
155
-            return self::retryFailedRewind($handler, $easy, $ctx);
156
-        }
157
-
158
-        return self::createRejection($easy, $ctx);
159
-    }
160
-
161
-    private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface
162
-    {
163
-        static $connectionErrors = [
164
-            \CURLE_OPERATION_TIMEOUTED => true,
165
-            \CURLE_COULDNT_RESOLVE_HOST => true,
166
-            \CURLE_COULDNT_CONNECT => true,
167
-            \CURLE_SSL_CONNECT_ERROR => true,
168
-            \CURLE_GOT_NOTHING => true,
169
-        ];
170
-
171
-        if ($easy->createResponseException) {
172
-            return P\Create::rejectionFor(
173
-                new RequestException(
174
-                    'An error was encountered while creating the response',
175
-                    $easy->request,
176
-                    $easy->response,
177
-                    $easy->createResponseException,
178
-                    $ctx
179
-                )
180
-            );
181
-        }
182
-
183
-        // If an exception was encountered during the onHeaders event, then
184
-        // return a rejected promise that wraps that exception.
185
-        if ($easy->onHeadersException) {
186
-            return P\Create::rejectionFor(
187
-                new RequestException(
188
-                    'An error was encountered during the on_headers event',
189
-                    $easy->request,
190
-                    $easy->response,
191
-                    $easy->onHeadersException,
192
-                    $ctx
193
-                )
194
-            );
195
-        }
196
-
197
-        $message = \sprintf(
198
-            'cURL error %s: %s (%s)',
199
-            $ctx['errno'],
200
-            $ctx['error'],
201
-            'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
202
-        );
203
-        $uriString = (string) $easy->request->getUri();
204
-        if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) {
205
-            $message .= \sprintf(' for %s', $uriString);
206
-        }
207
-
208
-        // Create a connection exception if it was a specific error code.
209
-        $error = isset($connectionErrors[$easy->errno])
210
-            ? new ConnectException($message, $easy->request, null, $ctx)
211
-            : new RequestException($message, $easy->request, $easy->response, null, $ctx);
212
-
213
-        return P\Create::rejectionFor($error);
214
-    }
215
-
216
-    /**
217
-     * @return array<int|string, mixed>
218
-     */
219
-    private function getDefaultConf(EasyHandle $easy): array
220
-    {
221
-        $conf = [
222
-            '_headers' => $easy->request->getHeaders(),
223
-            \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
224
-            \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
225
-            \CURLOPT_RETURNTRANSFER => false,
226
-            \CURLOPT_HEADER => false,
227
-            \CURLOPT_CONNECTTIMEOUT => 300,
228
-        ];
229
-
230
-        if (\defined('CURLOPT_PROTOCOLS')) {
231
-            $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
232
-        }
233
-
234
-        $version = $easy->request->getProtocolVersion();
235
-        if ($version == 1.1) {
236
-            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
237
-        } elseif ($version == 2.0) {
238
-            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
239
-        } else {
240
-            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
241
-        }
242
-
243
-        return $conf;
244
-    }
245
-
246
-    private function applyMethod(EasyHandle $easy, array &$conf): void
247
-    {
248
-        $body = $easy->request->getBody();
249
-        $size = $body->getSize();
250
-
251
-        if ($size === null || $size > 0) {
252
-            $this->applyBody($easy->request, $easy->options, $conf);
253
-
254
-            return;
255
-        }
256
-
257
-        $method = $easy->request->getMethod();
258
-        if ($method === 'PUT' || $method === 'POST') {
259
-            // See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
260
-            if (!$easy->request->hasHeader('Content-Length')) {
261
-                $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
262
-            }
263
-        } elseif ($method === 'HEAD') {
264
-            $conf[\CURLOPT_NOBODY] = true;
265
-            unset(
266
-                $conf[\CURLOPT_WRITEFUNCTION],
267
-                $conf[\CURLOPT_READFUNCTION],
268
-                $conf[\CURLOPT_FILE],
269
-                $conf[\CURLOPT_INFILE]
270
-            );
271
-        }
272
-    }
273
-
274
-    private function applyBody(RequestInterface $request, array $options, array &$conf): void
275
-    {
276
-        $size = $request->hasHeader('Content-Length')
277
-            ? (int) $request->getHeaderLine('Content-Length')
278
-            : null;
279
-
280
-        // Send the body as a string if the size is less than 1MB OR if the
281
-        // [curl][body_as_string] request value is set.
282
-        if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) {
283
-            $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody();
284
-            // Don't duplicate the Content-Length header
285
-            $this->removeHeader('Content-Length', $conf);
286
-            $this->removeHeader('Transfer-Encoding', $conf);
287
-        } else {
288
-            $conf[\CURLOPT_UPLOAD] = true;
289
-            if ($size !== null) {
290
-                $conf[\CURLOPT_INFILESIZE] = $size;
291
-                $this->removeHeader('Content-Length', $conf);
292
-            }
293
-            $body = $request->getBody();
294
-            if ($body->isSeekable()) {
295
-                $body->rewind();
296
-            }
297
-            $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) {
298
-                return $body->read($length);
299
-            };
300
-        }
301
-
302
-        // If the Expect header is not present, prevent curl from adding it
303
-        if (!$request->hasHeader('Expect')) {
304
-            $conf[\CURLOPT_HTTPHEADER][] = 'Expect:';
305
-        }
306
-
307
-        // cURL sometimes adds a content-type by default. Prevent this.
308
-        if (!$request->hasHeader('Content-Type')) {
309
-            $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:';
310
-        }
311
-    }
312
-
313
-    private function applyHeaders(EasyHandle $easy, array &$conf): void
314
-    {
315
-        foreach ($conf['_headers'] as $name => $values) {
316
-            foreach ($values as $value) {
317
-                $value = (string) $value;
318
-                if ($value === '') {
319
-                    // cURL requires a special format for empty headers.
320
-                    // See https://github.com/guzzle/guzzle/issues/1882 for more details.
321
-                    $conf[\CURLOPT_HTTPHEADER][] = "$name;";
322
-                } else {
323
-                    $conf[\CURLOPT_HTTPHEADER][] = "$name: $value";
324
-                }
325
-            }
326
-        }
327
-
328
-        // Remove the Accept header if one was not set
329
-        if (!$easy->request->hasHeader('Accept')) {
330
-            $conf[\CURLOPT_HTTPHEADER][] = 'Accept:';
331
-        }
332
-    }
333
-
334
-    /**
335
-     * Remove a header from the options array.
336
-     *
337
-     * @param string $name    Case-insensitive header to remove
338
-     * @param array  $options Array of options to modify
339
-     */
340
-    private function removeHeader(string $name, array &$options): void
341
-    {
342
-        foreach (\array_keys($options['_headers']) as $key) {
343
-            if (!\strcasecmp($key, $name)) {
344
-                unset($options['_headers'][$key]);
345
-
346
-                return;
347
-            }
348
-        }
349
-    }
350
-
351
-    private function applyHandlerOptions(EasyHandle $easy, array &$conf): void
352
-    {
353
-        $options = $easy->options;
354
-        if (isset($options['verify'])) {
355
-            if ($options['verify'] === false) {
356
-                unset($conf[\CURLOPT_CAINFO]);
357
-                $conf[\CURLOPT_SSL_VERIFYHOST] = 0;
358
-                $conf[\CURLOPT_SSL_VERIFYPEER] = false;
359
-            } else {
360
-                $conf[\CURLOPT_SSL_VERIFYHOST] = 2;
361
-                $conf[\CURLOPT_SSL_VERIFYPEER] = true;
362
-                if (\is_string($options['verify'])) {
363
-                    // Throw an error if the file/folder/link path is not valid or doesn't exist.
364
-                    if (!\file_exists($options['verify'])) {
365
-                        throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}");
366
-                    }
367
-                    // If it's a directory or a link to a directory use CURLOPT_CAPATH.
368
-                    // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
369
-                    if (
370
-                        \is_dir($options['verify'])
371
-                        || (
372
-                            \is_link($options['verify']) === true
373
-                            && ($verifyLink = \readlink($options['verify'])) !== false
374
-                            && \is_dir($verifyLink)
375
-                        )
376
-                    ) {
377
-                        $conf[\CURLOPT_CAPATH] = $options['verify'];
378
-                    } else {
379
-                        $conf[\CURLOPT_CAINFO] = $options['verify'];
380
-                    }
381
-                }
382
-            }
383
-        }
384
-
385
-        if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) {
386
-            $accept = $easy->request->getHeaderLine('Accept-Encoding');
387
-            if ($accept) {
388
-                $conf[\CURLOPT_ENCODING] = $accept;
389
-            } else {
390
-                // The empty string enables all available decoders and implicitly
391
-                // sets a matching 'Accept-Encoding' header.
392
-                $conf[\CURLOPT_ENCODING] = '';
393
-                // But as the user did not specify any acceptable encodings we need
394
-                // to overwrite this implicit header with an empty one.
395
-                $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
396
-            }
397
-        }
398
-
399
-        if (!isset($options['sink'])) {
400
-            // Use a default temp stream if no sink was set.
401
-            $options['sink'] = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+');
402
-        }
403
-        $sink = $options['sink'];
404
-        if (!\is_string($sink)) {
405
-            $sink = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
406
-        } elseif (!\is_dir(\dirname($sink))) {
407
-            // Ensure that the directory exists before failing in curl.
408
-            throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink));
409
-        } else {
410
-            $sink = new LazyOpenStream($sink, 'w+');
411
-        }
412
-        $easy->sink = $sink;
413
-        $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int {
414
-            return $sink->write($write);
415
-        };
416
-
417
-        $timeoutRequiresNoSignal = false;
418
-        if (isset($options['timeout'])) {
419
-            $timeoutRequiresNoSignal |= $options['timeout'] < 1;
420
-            $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
421
-        }
422
-
423
-        // CURL default value is CURL_IPRESOLVE_WHATEVER
424
-        if (isset($options['force_ip_resolve'])) {
425
-            if ('v4' === $options['force_ip_resolve']) {
426
-                $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4;
427
-            } elseif ('v6' === $options['force_ip_resolve']) {
428
-                $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6;
429
-            }
430
-        }
431
-
432
-        if (isset($options['connect_timeout'])) {
433
-            $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
434
-            $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
435
-        }
436
-
437
-        if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') {
438
-            $conf[\CURLOPT_NOSIGNAL] = true;
439
-        }
440
-
441
-        if (isset($options['proxy'])) {
442
-            if (!\is_array($options['proxy'])) {
443
-                $conf[\CURLOPT_PROXY] = $options['proxy'];
444
-            } else {
445
-                $scheme = $easy->request->getUri()->getScheme();
446
-                if (isset($options['proxy'][$scheme])) {
447
-                    $host = $easy->request->getUri()->getHost();
448
-                    if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
449
-                        unset($conf[\CURLOPT_PROXY]);
450
-                    } else {
451
-                        $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme];
452
-                    }
453
-                }
454
-            }
455
-        }
456
-
457
-        if (isset($options['crypto_method'])) {
458
-            if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
459
-                if (!defined('CURL_SSLVERSION_TLSv1_0')) {
460
-                    throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL');
461
-                }
462
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
463
-            } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
464
-                if (!defined('CURL_SSLVERSION_TLSv1_1')) {
465
-                    throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL');
466
-                }
467
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
468
-            } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
469
-                if (!defined('CURL_SSLVERSION_TLSv1_2')) {
470
-                    throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
471
-                }
472
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
473
-            } elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
474
-                if (!defined('CURL_SSLVERSION_TLSv1_3')) {
475
-                    throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
476
-                }
477
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
478
-            } else {
479
-                throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
480
-            }
481
-        }
482
-
483
-        if (isset($options['cert'])) {
484
-            $cert = $options['cert'];
485
-            if (\is_array($cert)) {
486
-                $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1];
487
-                $cert = $cert[0];
488
-            }
489
-            if (!\file_exists($cert)) {
490
-                throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
491
-            }
492
-            // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
493
-            // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
494
-            $ext = pathinfo($cert, \PATHINFO_EXTENSION);
495
-            if (preg_match('#^(der|p12)$#i', $ext)) {
496
-                $conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext);
497
-            }
498
-            $conf[\CURLOPT_SSLCERT] = $cert;
499
-        }
500
-
501
-        if (isset($options['ssl_key'])) {
502
-            if (\is_array($options['ssl_key'])) {
503
-                if (\count($options['ssl_key']) === 2) {
504
-                    [$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key'];
505
-                } else {
506
-                    [$sslKey] = $options['ssl_key'];
507
-                }
508
-            }
509
-
510
-            $sslKey = $sslKey ?? $options['ssl_key'];
511
-
512
-            if (!\file_exists($sslKey)) {
513
-                throw new \InvalidArgumentException("SSL private key not found: {$sslKey}");
514
-            }
515
-            $conf[\CURLOPT_SSLKEY] = $sslKey;
516
-        }
517
-
518
-        if (isset($options['progress'])) {
519
-            $progress = $options['progress'];
520
-            if (!\is_callable($progress)) {
521
-                throw new \InvalidArgumentException('progress client option must be callable');
522
-            }
523
-            $conf[\CURLOPT_NOPROGRESS] = false;
524
-            $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) {
525
-                $progress($downloadSize, $downloaded, $uploadSize, $uploaded);
526
-            };
527
-        }
528
-
529
-        if (!empty($options['debug'])) {
530
-            $conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']);
531
-            $conf[\CURLOPT_VERBOSE] = true;
532
-        }
533
-    }
534
-
535
-    /**
536
-     * This function ensures that a response was set on a transaction. If one
537
-     * was not set, then the request is retried if possible. This error
538
-     * typically means you are sending a payload, curl encountered a
539
-     * "Connection died, retrying a fresh connect" error, tried to rewind the
540
-     * stream, and then encountered a "necessary data rewind wasn't possible"
541
-     * error, causing the request to be sent through curl_multi_info_read()
542
-     * without an error status.
543
-     *
544
-     * @param callable(RequestInterface, array): PromiseInterface $handler
545
-     */
546
-    private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx): PromiseInterface
547
-    {
548
-        try {
549
-            // Only rewind if the body has been read from.
550
-            $body = $easy->request->getBody();
551
-            if ($body->tell() > 0) {
552
-                $body->rewind();
553
-            }
554
-        } catch (\RuntimeException $e) {
555
-            $ctx['error'] = 'The connection unexpectedly failed without '
556
-                .'providing an error. The request would have been retried, '
557
-                .'but attempting to rewind the request body failed. '
558
-                .'Exception: '.$e;
559
-
560
-            return self::createRejection($easy, $ctx);
561
-        }
562
-
563
-        // Retry no more than 3 times before giving up.
564
-        if (!isset($easy->options['_curl_retries'])) {
565
-            $easy->options['_curl_retries'] = 1;
566
-        } elseif ($easy->options['_curl_retries'] == 2) {
567
-            $ctx['error'] = 'The cURL request was retried 3 times '
568
-                .'and did not succeed. The most likely reason for the failure '
569
-                .'is that cURL was unable to rewind the body of the request '
570
-                .'and subsequent retries resulted in the same error. Turn on '
571
-                .'the debug option to see what went wrong. See '
572
-                .'https://bugs.php.net/bug.php?id=47204 for more information.';
573
-
574
-            return self::createRejection($easy, $ctx);
575
-        } else {
576
-            ++$easy->options['_curl_retries'];
577
-        }
578
-
579
-        return $handler($easy->request, $easy->options);
580
-    }
581
-
582
-    private function createHeaderFn(EasyHandle $easy): callable
583
-    {
584
-        if (isset($easy->options['on_headers'])) {
585
-            $onHeaders = $easy->options['on_headers'];
586
-
587
-            if (!\is_callable($onHeaders)) {
588
-                throw new \InvalidArgumentException('on_headers must be callable');
589
-            }
590
-        } else {
591
-            $onHeaders = null;
592
-        }
593
-
594
-        return static function ($ch, $h) use (
595
-            $onHeaders,
596
-            $easy,
597
-            &$startingResponse
598
-        ) {
599
-            $value = \trim($h);
600
-            if ($value === '') {
601
-                $startingResponse = true;
602
-                try {
603
-                    $easy->createResponse();
604
-                } catch (\Exception $e) {
605
-                    $easy->createResponseException = $e;
606
-
607
-                    return -1;
608
-                }
609
-                if ($onHeaders !== null) {
610
-                    try {
611
-                        $onHeaders($easy->response);
612
-                    } catch (\Exception $e) {
613
-                        // Associate the exception with the handle and trigger
614
-                        // a curl header write error by returning 0.
615
-                        $easy->onHeadersException = $e;
616
-
617
-                        return -1;
618
-                    }
619
-                }
620
-            } elseif ($startingResponse) {
621
-                $startingResponse = false;
622
-                $easy->headers = [$value];
623
-            } else {
624
-                $easy->headers[] = $value;
625
-            }
626
-
627
-            return \strlen($h);
628
-        };
629
-    }
630
-
631
-    public function __destruct()
632
-    {
633
-        foreach ($this->handles as $id => $handle) {
634
-            \curl_close($handle);
635
-            unset($this->handles[$id]);
636
-        }
637
-    }
22
+	public const CURL_VERSION_STR = 'curl_version';
23
+
24
+	/**
25
+	 * @deprecated
26
+	 */
27
+	public const LOW_CURL_VERSION_NUMBER = '7.21.2';
28
+
29
+	/**
30
+	 * @var resource[]|\CurlHandle[]
31
+	 */
32
+	private $handles = [];
33
+
34
+	/**
35
+	 * @var int Total number of idle handles to keep in cache
36
+	 */
37
+	private $maxHandles;
38
+
39
+	/**
40
+	 * @param int $maxHandles Maximum number of idle handles.
41
+	 */
42
+	public function __construct(int $maxHandles)
43
+	{
44
+		$this->maxHandles = $maxHandles;
45
+	}
46
+
47
+	public function create(RequestInterface $request, array $options): EasyHandle
48
+	{
49
+		if (isset($options['curl']['body_as_string'])) {
50
+			$options['_body_as_string'] = $options['curl']['body_as_string'];
51
+			unset($options['curl']['body_as_string']);
52
+		}
53
+
54
+		$easy = new EasyHandle();
55
+		$easy->request = $request;
56
+		$easy->options = $options;
57
+		$conf = $this->getDefaultConf($easy);
58
+		$this->applyMethod($easy, $conf);
59
+		$this->applyHandlerOptions($easy, $conf);
60
+		$this->applyHeaders($easy, $conf);
61
+		unset($conf['_headers']);
62
+
63
+		// Add handler options from the request configuration options
64
+		if (isset($options['curl'])) {
65
+			$conf = \array_replace($conf, $options['curl']);
66
+		}
67
+
68
+		$conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
69
+		$easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init();
70
+		curl_setopt_array($easy->handle, $conf);
71
+
72
+		return $easy;
73
+	}
74
+
75
+	public function release(EasyHandle $easy): void
76
+	{
77
+		$resource = $easy->handle;
78
+		unset($easy->handle);
79
+
80
+		if (\count($this->handles) >= $this->maxHandles) {
81
+			\curl_close($resource);
82
+		} else {
83
+			// Remove all callback functions as they can hold onto references
84
+			// and are not cleaned up by curl_reset. Using curl_setopt_array
85
+			// does not work for some reason, so removing each one
86
+			// individually.
87
+			\curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null);
88
+			\curl_setopt($resource, \CURLOPT_READFUNCTION, null);
89
+			\curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null);
90
+			\curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null);
91
+			\curl_reset($resource);
92
+			$this->handles[] = $resource;
93
+		}
94
+	}
95
+
96
+	/**
97
+	 * Completes a cURL transaction, either returning a response promise or a
98
+	 * rejected promise.
99
+	 *
100
+	 * @param callable(RequestInterface, array): PromiseInterface $handler
101
+	 * @param CurlFactoryInterface                                $factory Dictates how the handle is released
102
+	 */
103
+	public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface
104
+	{
105
+		if (isset($easy->options['on_stats'])) {
106
+			self::invokeStats($easy);
107
+		}
108
+
109
+		if (!$easy->response || $easy->errno) {
110
+			return self::finishError($handler, $easy, $factory);
111
+		}
112
+
113
+		// Return the response if it is present and there is no error.
114
+		$factory->release($easy);
115
+
116
+		// Rewind the body of the response if possible.
117
+		$body = $easy->response->getBody();
118
+		if ($body->isSeekable()) {
119
+			$body->rewind();
120
+		}
121
+
122
+		return new FulfilledPromise($easy->response);
123
+	}
124
+
125
+	private static function invokeStats(EasyHandle $easy): void
126
+	{
127
+		$curlStats = \curl_getinfo($easy->handle);
128
+		$curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME);
129
+		$stats = new TransferStats(
130
+			$easy->request,
131
+			$easy->response,
132
+			$curlStats['total_time'],
133
+			$easy->errno,
134
+			$curlStats
135
+		);
136
+		($easy->options['on_stats'])($stats);
137
+	}
138
+
139
+	/**
140
+	 * @param callable(RequestInterface, array): PromiseInterface $handler
141
+	 */
142
+	private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface
143
+	{
144
+		// Get error information and release the handle to the factory.
145
+		$ctx = [
146
+			'errno' => $easy->errno,
147
+			'error' => \curl_error($easy->handle),
148
+			'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME),
149
+		] + \curl_getinfo($easy->handle);
150
+		$ctx[self::CURL_VERSION_STR] = \curl_version()['version'];
151
+		$factory->release($easy);
152
+
153
+		// Retry when nothing is present or when curl failed to rewind.
154
+		if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) {
155
+			return self::retryFailedRewind($handler, $easy, $ctx);
156
+		}
157
+
158
+		return self::createRejection($easy, $ctx);
159
+	}
160
+
161
+	private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface
162
+	{
163
+		static $connectionErrors = [
164
+			\CURLE_OPERATION_TIMEOUTED => true,
165
+			\CURLE_COULDNT_RESOLVE_HOST => true,
166
+			\CURLE_COULDNT_CONNECT => true,
167
+			\CURLE_SSL_CONNECT_ERROR => true,
168
+			\CURLE_GOT_NOTHING => true,
169
+		];
170
+
171
+		if ($easy->createResponseException) {
172
+			return P\Create::rejectionFor(
173
+				new RequestException(
174
+					'An error was encountered while creating the response',
175
+					$easy->request,
176
+					$easy->response,
177
+					$easy->createResponseException,
178
+					$ctx
179
+				)
180
+			);
181
+		}
182
+
183
+		// If an exception was encountered during the onHeaders event, then
184
+		// return a rejected promise that wraps that exception.
185
+		if ($easy->onHeadersException) {
186
+			return P\Create::rejectionFor(
187
+				new RequestException(
188
+					'An error was encountered during the on_headers event',
189
+					$easy->request,
190
+					$easy->response,
191
+					$easy->onHeadersException,
192
+					$ctx
193
+				)
194
+			);
195
+		}
196
+
197
+		$message = \sprintf(
198
+			'cURL error %s: %s (%s)',
199
+			$ctx['errno'],
200
+			$ctx['error'],
201
+			'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
202
+		);
203
+		$uriString = (string) $easy->request->getUri();
204
+		if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) {
205
+			$message .= \sprintf(' for %s', $uriString);
206
+		}
207
+
208
+		// Create a connection exception if it was a specific error code.
209
+		$error = isset($connectionErrors[$easy->errno])
210
+			? new ConnectException($message, $easy->request, null, $ctx)
211
+			: new RequestException($message, $easy->request, $easy->response, null, $ctx);
212
+
213
+		return P\Create::rejectionFor($error);
214
+	}
215
+
216
+	/**
217
+	 * @return array<int|string, mixed>
218
+	 */
219
+	private function getDefaultConf(EasyHandle $easy): array
220
+	{
221
+		$conf = [
222
+			'_headers' => $easy->request->getHeaders(),
223
+			\CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
224
+			\CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
225
+			\CURLOPT_RETURNTRANSFER => false,
226
+			\CURLOPT_HEADER => false,
227
+			\CURLOPT_CONNECTTIMEOUT => 300,
228
+		];
229
+
230
+		if (\defined('CURLOPT_PROTOCOLS')) {
231
+			$conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
232
+		}
233
+
234
+		$version = $easy->request->getProtocolVersion();
235
+		if ($version == 1.1) {
236
+			$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
237
+		} elseif ($version == 2.0) {
238
+			$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
239
+		} else {
240
+			$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
241
+		}
242
+
243
+		return $conf;
244
+	}
245
+
246
+	private function applyMethod(EasyHandle $easy, array &$conf): void
247
+	{
248
+		$body = $easy->request->getBody();
249
+		$size = $body->getSize();
250
+
251
+		if ($size === null || $size > 0) {
252
+			$this->applyBody($easy->request, $easy->options, $conf);
253
+
254
+			return;
255
+		}
256
+
257
+		$method = $easy->request->getMethod();
258
+		if ($method === 'PUT' || $method === 'POST') {
259
+			// See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
260
+			if (!$easy->request->hasHeader('Content-Length')) {
261
+				$conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
262
+			}
263
+		} elseif ($method === 'HEAD') {
264
+			$conf[\CURLOPT_NOBODY] = true;
265
+			unset(
266
+				$conf[\CURLOPT_WRITEFUNCTION],
267
+				$conf[\CURLOPT_READFUNCTION],
268
+				$conf[\CURLOPT_FILE],
269
+				$conf[\CURLOPT_INFILE]
270
+			);
271
+		}
272
+	}
273
+
274
+	private function applyBody(RequestInterface $request, array $options, array &$conf): void
275
+	{
276
+		$size = $request->hasHeader('Content-Length')
277
+			? (int) $request->getHeaderLine('Content-Length')
278
+			: null;
279
+
280
+		// Send the body as a string if the size is less than 1MB OR if the
281
+		// [curl][body_as_string] request value is set.
282
+		if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) {
283
+			$conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody();
284
+			// Don't duplicate the Content-Length header
285
+			$this->removeHeader('Content-Length', $conf);
286
+			$this->removeHeader('Transfer-Encoding', $conf);
287
+		} else {
288
+			$conf[\CURLOPT_UPLOAD] = true;
289
+			if ($size !== null) {
290
+				$conf[\CURLOPT_INFILESIZE] = $size;
291
+				$this->removeHeader('Content-Length', $conf);
292
+			}
293
+			$body = $request->getBody();
294
+			if ($body->isSeekable()) {
295
+				$body->rewind();
296
+			}
297
+			$conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) {
298
+				return $body->read($length);
299
+			};
300
+		}
301
+
302
+		// If the Expect header is not present, prevent curl from adding it
303
+		if (!$request->hasHeader('Expect')) {
304
+			$conf[\CURLOPT_HTTPHEADER][] = 'Expect:';
305
+		}
306
+
307
+		// cURL sometimes adds a content-type by default. Prevent this.
308
+		if (!$request->hasHeader('Content-Type')) {
309
+			$conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:';
310
+		}
311
+	}
312
+
313
+	private function applyHeaders(EasyHandle $easy, array &$conf): void
314
+	{
315
+		foreach ($conf['_headers'] as $name => $values) {
316
+			foreach ($values as $value) {
317
+				$value = (string) $value;
318
+				if ($value === '') {
319
+					// cURL requires a special format for empty headers.
320
+					// See https://github.com/guzzle/guzzle/issues/1882 for more details.
321
+					$conf[\CURLOPT_HTTPHEADER][] = "$name;";
322
+				} else {
323
+					$conf[\CURLOPT_HTTPHEADER][] = "$name: $value";
324
+				}
325
+			}
326
+		}
327
+
328
+		// Remove the Accept header if one was not set
329
+		if (!$easy->request->hasHeader('Accept')) {
330
+			$conf[\CURLOPT_HTTPHEADER][] = 'Accept:';
331
+		}
332
+	}
333
+
334
+	/**
335
+	 * Remove a header from the options array.
336
+	 *
337
+	 * @param string $name    Case-insensitive header to remove
338
+	 * @param array  $options Array of options to modify
339
+	 */
340
+	private function removeHeader(string $name, array &$options): void
341
+	{
342
+		foreach (\array_keys($options['_headers']) as $key) {
343
+			if (!\strcasecmp($key, $name)) {
344
+				unset($options['_headers'][$key]);
345
+
346
+				return;
347
+			}
348
+		}
349
+	}
350
+
351
+	private function applyHandlerOptions(EasyHandle $easy, array &$conf): void
352
+	{
353
+		$options = $easy->options;
354
+		if (isset($options['verify'])) {
355
+			if ($options['verify'] === false) {
356
+				unset($conf[\CURLOPT_CAINFO]);
357
+				$conf[\CURLOPT_SSL_VERIFYHOST] = 0;
358
+				$conf[\CURLOPT_SSL_VERIFYPEER] = false;
359
+			} else {
360
+				$conf[\CURLOPT_SSL_VERIFYHOST] = 2;
361
+				$conf[\CURLOPT_SSL_VERIFYPEER] = true;
362
+				if (\is_string($options['verify'])) {
363
+					// Throw an error if the file/folder/link path is not valid or doesn't exist.
364
+					if (!\file_exists($options['verify'])) {
365
+						throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}");
366
+					}
367
+					// If it's a directory or a link to a directory use CURLOPT_CAPATH.
368
+					// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
369
+					if (
370
+						\is_dir($options['verify'])
371
+						|| (
372
+							\is_link($options['verify']) === true
373
+							&& ($verifyLink = \readlink($options['verify'])) !== false
374
+							&& \is_dir($verifyLink)
375
+						)
376
+					) {
377
+						$conf[\CURLOPT_CAPATH] = $options['verify'];
378
+					} else {
379
+						$conf[\CURLOPT_CAINFO] = $options['verify'];
380
+					}
381
+				}
382
+			}
383
+		}
384
+
385
+		if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) {
386
+			$accept = $easy->request->getHeaderLine('Accept-Encoding');
387
+			if ($accept) {
388
+				$conf[\CURLOPT_ENCODING] = $accept;
389
+			} else {
390
+				// The empty string enables all available decoders and implicitly
391
+				// sets a matching 'Accept-Encoding' header.
392
+				$conf[\CURLOPT_ENCODING] = '';
393
+				// But as the user did not specify any acceptable encodings we need
394
+				// to overwrite this implicit header with an empty one.
395
+				$conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
396
+			}
397
+		}
398
+
399
+		if (!isset($options['sink'])) {
400
+			// Use a default temp stream if no sink was set.
401
+			$options['sink'] = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+');
402
+		}
403
+		$sink = $options['sink'];
404
+		if (!\is_string($sink)) {
405
+			$sink = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
406
+		} elseif (!\is_dir(\dirname($sink))) {
407
+			// Ensure that the directory exists before failing in curl.
408
+			throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink));
409
+		} else {
410
+			$sink = new LazyOpenStream($sink, 'w+');
411
+		}
412
+		$easy->sink = $sink;
413
+		$conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int {
414
+			return $sink->write($write);
415
+		};
416
+
417
+		$timeoutRequiresNoSignal = false;
418
+		if (isset($options['timeout'])) {
419
+			$timeoutRequiresNoSignal |= $options['timeout'] < 1;
420
+			$conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
421
+		}
422
+
423
+		// CURL default value is CURL_IPRESOLVE_WHATEVER
424
+		if (isset($options['force_ip_resolve'])) {
425
+			if ('v4' === $options['force_ip_resolve']) {
426
+				$conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4;
427
+			} elseif ('v6' === $options['force_ip_resolve']) {
428
+				$conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6;
429
+			}
430
+		}
431
+
432
+		if (isset($options['connect_timeout'])) {
433
+			$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
434
+			$conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
435
+		}
436
+
437
+		if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') {
438
+			$conf[\CURLOPT_NOSIGNAL] = true;
439
+		}
440
+
441
+		if (isset($options['proxy'])) {
442
+			if (!\is_array($options['proxy'])) {
443
+				$conf[\CURLOPT_PROXY] = $options['proxy'];
444
+			} else {
445
+				$scheme = $easy->request->getUri()->getScheme();
446
+				if (isset($options['proxy'][$scheme])) {
447
+					$host = $easy->request->getUri()->getHost();
448
+					if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
449
+						unset($conf[\CURLOPT_PROXY]);
450
+					} else {
451
+						$conf[\CURLOPT_PROXY] = $options['proxy'][$scheme];
452
+					}
453
+				}
454
+			}
455
+		}
456
+
457
+		if (isset($options['crypto_method'])) {
458
+			if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
459
+				if (!defined('CURL_SSLVERSION_TLSv1_0')) {
460
+					throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL');
461
+				}
462
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
463
+			} elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
464
+				if (!defined('CURL_SSLVERSION_TLSv1_1')) {
465
+					throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL');
466
+				}
467
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
468
+			} elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
469
+				if (!defined('CURL_SSLVERSION_TLSv1_2')) {
470
+					throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
471
+				}
472
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
473
+			} elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
474
+				if (!defined('CURL_SSLVERSION_TLSv1_3')) {
475
+					throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
476
+				}
477
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
478
+			} else {
479
+				throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
480
+			}
481
+		}
482
+
483
+		if (isset($options['cert'])) {
484
+			$cert = $options['cert'];
485
+			if (\is_array($cert)) {
486
+				$conf[\CURLOPT_SSLCERTPASSWD] = $cert[1];
487
+				$cert = $cert[0];
488
+			}
489
+			if (!\file_exists($cert)) {
490
+				throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
491
+			}
492
+			// OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
493
+			// see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
494
+			$ext = pathinfo($cert, \PATHINFO_EXTENSION);
495
+			if (preg_match('#^(der|p12)$#i', $ext)) {
496
+				$conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext);
497
+			}
498
+			$conf[\CURLOPT_SSLCERT] = $cert;
499
+		}
500
+
501
+		if (isset($options['ssl_key'])) {
502
+			if (\is_array($options['ssl_key'])) {
503
+				if (\count($options['ssl_key']) === 2) {
504
+					[$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key'];
505
+				} else {
506
+					[$sslKey] = $options['ssl_key'];
507
+				}
508
+			}
509
+
510
+			$sslKey = $sslKey ?? $options['ssl_key'];
511
+
512
+			if (!\file_exists($sslKey)) {
513
+				throw new \InvalidArgumentException("SSL private key not found: {$sslKey}");
514
+			}
515
+			$conf[\CURLOPT_SSLKEY] = $sslKey;
516
+		}
517
+
518
+		if (isset($options['progress'])) {
519
+			$progress = $options['progress'];
520
+			if (!\is_callable($progress)) {
521
+				throw new \InvalidArgumentException('progress client option must be callable');
522
+			}
523
+			$conf[\CURLOPT_NOPROGRESS] = false;
524
+			$conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) {
525
+				$progress($downloadSize, $downloaded, $uploadSize, $uploaded);
526
+			};
527
+		}
528
+
529
+		if (!empty($options['debug'])) {
530
+			$conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']);
531
+			$conf[\CURLOPT_VERBOSE] = true;
532
+		}
533
+	}
534
+
535
+	/**
536
+	 * This function ensures that a response was set on a transaction. If one
537
+	 * was not set, then the request is retried if possible. This error
538
+	 * typically means you are sending a payload, curl encountered a
539
+	 * "Connection died, retrying a fresh connect" error, tried to rewind the
540
+	 * stream, and then encountered a "necessary data rewind wasn't possible"
541
+	 * error, causing the request to be sent through curl_multi_info_read()
542
+	 * without an error status.
543
+	 *
544
+	 * @param callable(RequestInterface, array): PromiseInterface $handler
545
+	 */
546
+	private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx): PromiseInterface
547
+	{
548
+		try {
549
+			// Only rewind if the body has been read from.
550
+			$body = $easy->request->getBody();
551
+			if ($body->tell() > 0) {
552
+				$body->rewind();
553
+			}
554
+		} catch (\RuntimeException $e) {
555
+			$ctx['error'] = 'The connection unexpectedly failed without '
556
+				.'providing an error. The request would have been retried, '
557
+				.'but attempting to rewind the request body failed. '
558
+				.'Exception: '.$e;
559
+
560
+			return self::createRejection($easy, $ctx);
561
+		}
562
+
563
+		// Retry no more than 3 times before giving up.
564
+		if (!isset($easy->options['_curl_retries'])) {
565
+			$easy->options['_curl_retries'] = 1;
566
+		} elseif ($easy->options['_curl_retries'] == 2) {
567
+			$ctx['error'] = 'The cURL request was retried 3 times '
568
+				.'and did not succeed. The most likely reason for the failure '
569
+				.'is that cURL was unable to rewind the body of the request '
570
+				.'and subsequent retries resulted in the same error. Turn on '
571
+				.'the debug option to see what went wrong. See '
572
+				.'https://bugs.php.net/bug.php?id=47204 for more information.';
573
+
574
+			return self::createRejection($easy, $ctx);
575
+		} else {
576
+			++$easy->options['_curl_retries'];
577
+		}
578
+
579
+		return $handler($easy->request, $easy->options);
580
+	}
581
+
582
+	private function createHeaderFn(EasyHandle $easy): callable
583
+	{
584
+		if (isset($easy->options['on_headers'])) {
585
+			$onHeaders = $easy->options['on_headers'];
586
+
587
+			if (!\is_callable($onHeaders)) {
588
+				throw new \InvalidArgumentException('on_headers must be callable');
589
+			}
590
+		} else {
591
+			$onHeaders = null;
592
+		}
593
+
594
+		return static function ($ch, $h) use (
595
+			$onHeaders,
596
+			$easy,
597
+			&$startingResponse
598
+		) {
599
+			$value = \trim($h);
600
+			if ($value === '') {
601
+				$startingResponse = true;
602
+				try {
603
+					$easy->createResponse();
604
+				} catch (\Exception $e) {
605
+					$easy->createResponseException = $e;
606
+
607
+					return -1;
608
+				}
609
+				if ($onHeaders !== null) {
610
+					try {
611
+						$onHeaders($easy->response);
612
+					} catch (\Exception $e) {
613
+						// Associate the exception with the handle and trigger
614
+						// a curl header write error by returning 0.
615
+						$easy->onHeadersException = $e;
616
+
617
+						return -1;
618
+					}
619
+				}
620
+			} elseif ($startingResponse) {
621
+				$startingResponse = false;
622
+				$easy->headers = [$value];
623
+			} else {
624
+				$easy->headers[] = $value;
625
+			}
626
+
627
+			return \strlen($h);
628
+		};
629
+	}
630
+
631
+	public function __destruct()
632
+	{
633
+		foreach ($this->handles as $id => $handle) {
634
+			\curl_close($handle);
635
+			unset($this->handles[$id]);
636
+		}
637
+	}
638 638
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
             $ctx['error'],
201 201
             'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
202 202
         );
203
-        $uriString = (string) $easy->request->getUri();
203
+        $uriString = (string)$easy->request->getUri();
204 204
         if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) {
205 205
             $message .= \sprintf(' for %s', $uriString);
206 206
         }
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
         $conf = [
222 222
             '_headers' => $easy->request->getHeaders(),
223 223
             \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
224
-            \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
224
+            \CURLOPT_URL => (string)$easy->request->getUri()->withFragment(''),
225 225
             \CURLOPT_RETURNTRANSFER => false,
226 226
             \CURLOPT_HEADER => false,
227 227
             \CURLOPT_CONNECTTIMEOUT => 300,
@@ -274,13 +274,13 @@  discard block
 block discarded – undo
274 274
     private function applyBody(RequestInterface $request, array $options, array &$conf): void
275 275
     {
276 276
         $size = $request->hasHeader('Content-Length')
277
-            ? (int) $request->getHeaderLine('Content-Length')
277
+            ? (int)$request->getHeaderLine('Content-Length')
278 278
             : null;
279 279
 
280 280
         // Send the body as a string if the size is less than 1MB OR if the
281 281
         // [curl][body_as_string] request value is set.
282 282
         if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) {
283
-            $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody();
283
+            $conf[\CURLOPT_POSTFIELDS] = (string)$request->getBody();
284 284
             // Don't duplicate the Content-Length header
285 285
             $this->removeHeader('Content-Length', $conf);
286 286
             $this->removeHeader('Transfer-Encoding', $conf);
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
             if ($body->isSeekable()) {
295 295
                 $body->rewind();
296 296
             }
297
-            $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) {
297
+            $conf[\CURLOPT_READFUNCTION] = static function($ch, $fd, $length) use ($body) {
298 298
                 return $body->read($length);
299 299
             };
300 300
         }
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
     {
315 315
         foreach ($conf['_headers'] as $name => $values) {
316 316
             foreach ($values as $value) {
317
-                $value = (string) $value;
317
+                $value = (string)$value;
318 318
                 if ($value === '') {
319 319
                     // cURL requires a special format for empty headers.
320 320
                     // See https://github.com/guzzle/guzzle/issues/1882 for more details.
@@ -410,7 +410,7 @@  discard block
 block discarded – undo
410 410
             $sink = new LazyOpenStream($sink, 'w+');
411 411
         }
412 412
         $easy->sink = $sink;
413
-        $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int {
413
+        $conf[\CURLOPT_WRITEFUNCTION] = static function($ch, $write) use ($sink): int {
414 414
             return $sink->write($write);
415 415
         };
416 416
 
@@ -521,7 +521,7 @@  discard block
 block discarded – undo
521 521
                 throw new \InvalidArgumentException('progress client option must be callable');
522 522
             }
523 523
             $conf[\CURLOPT_NOPROGRESS] = false;
524
-            $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) {
524
+            $conf[\CURLOPT_PROGRESSFUNCTION] = static function($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) {
525 525
                 $progress($downloadSize, $downloaded, $uploadSize, $uploaded);
526 526
             };
527 527
         }
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
             $onHeaders = null;
592 592
         }
593 593
 
594
-        return static function ($ch, $h) use (
594
+        return static function($ch, $h) use (
595 595
             $onHeaders,
596 596
             $easy,
597 597
             &$startingResponse
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -17,8 +17,7 @@
 block discarded – undo
17 17
  *
18 18
  * @final
19 19
  */
20
-class CurlFactory implements CurlFactoryInterface
21
-{
20
+class CurlFactory implements CurlFactoryInterface {
22 21
     public const CURL_VERSION_STR = 'curl_version';
23 22
 
24 23
     /**
Please login to merge, or discard this patch.