PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
28.6 28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 All 130 releases
← All changes | vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlVersion.php +0 -206 28.4 → trunk View file →
@@ -1,206 +1,0 @@
1 -<?php
2 -
3 -namespace YoastSEO_Vendor\GuzzleHttp\Handler;
4 -
5 -/**
6 - * @internal
7 - */
8 -final class CurlVersion
9 -{
10 - private const MIN_VERSION = '7.21.2';
11 - private const TLS_12_VERSION = '7.34.0';
12 - private const TLS_13_VERSION = '7.52.0';
13 - private const CONNECTION_CAP_VERSION = '7.30.0';
14 - // CURLOPT_PIPEWAIT exists since libcurl 7.43.0, and multi handles have
15 - // multiplexed by default since 7.62.0 - but a 7.65.0-7.65.1 regression
16 - // dropped that default, which 7.65.2 restored, so 7.65.2 is the floor at
17 - // which PIPEWAIT is reliably effective.
18 - private const MULTIPLEX_VERSION = '7.65.2';
19 - // libcurl's connection matcher refuses to hand a transfer wanting
20 - // HTTP/1.x a pooled connection that already negotiated HTTP/2 or newer
21 - // from 7.77.0: ConnectionExists() in lib/url.c gained the check between
22 - // the 7.76.0 and 7.77.0 releases. The HTTP/2 branch of the check
23 - // regressed to a debug log in 8.11.0 (curl commit 433d730) and was
24 - // restored in 8.13.0 via the negotiation mask (curl commit db72b8d), so
25 - // 8.11.0 through 8.12.1 are vulnerable again.
26 - private const HTTP_VERSION_REUSE_MATCH_VERSION = '7.77.0';
27 - private const HTTP_VERSION_REUSE_MATCH_REGRESSION = '8.11.0';
28 - private const HTTP_VERSION_REUSE_MATCH_RESTORED = '8.13.0';
29 - // CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE restricts the ALPN offer to h2 only
30 - // since libcurl 8.10.0, and connection reuse matching stopped handing
31 - // lower-version connections to prior-knowledge transfers in 8.14.0; below
32 - // that, a required request could silently be sent over a reused HTTP/1.1
33 - // connection.
34 - private const REQUIRED_MULTIPLEX_VERSION = '8.14.0';
35 - // curl 7.52.0 introduced HTTPS proxy support, advertised by a feature bit
36 - // (a build can meet the version yet lack the feature). Earlier libcurl
37 - // mishandles an https:// proxy: before 7.50.2 it silently downgrades to a
38 - // plaintext HTTP proxy, and 7.50.2 through 7.51 reject it at connect time.
39 - private const HTTPS_PROXY_VERSION = '7.52.0';
40 - private const HANDLER_SHARING_VERSION = '7.35.0';
41 - private const SSL_SESSION_SHARING_VERSION = '8.6.0';
42 - // curl 7.57.0 added share-handle connection caches through
43 - // CURL_LOCK_DATA_CONNECT; older share objects can only hold DNS, TLS
44 - // session, and cookie data, never connections.
45 - private const SHARE_CONNECTION_CACHE_VERSION = '7.57.0';
46 - // curl 7.83.1 added proxy TLS-SRP to the connection-reuse match
47 - // (CVE-2022-27782); the proxy client certificate was matched from 7.52.0,
48 - // so proxy TLS credentials are trusted from 7.83.1 onwards.
49 - private const PROXY_TLS_CREDENTIAL_REUSE_VERSION = '7.83.1';
50 - // curl 8.19.0 fixed proxy tunnel reuse after credential changes
51 - // (CVE-2026-3784), but related proxy credential leak flaws were only
52 - // fixed in 8.20.0, so connection reuse is trusted from 8.20.0 onwards.
53 - private const PROXY_CREDENTIAL_REUSE_VERSION = '8.20.0';
54 - // curl 7.69.0 started comparing SOCKS proxy credentials when matching
55 - // connections for reuse (curl #4835); older libcurl matches a SOCKS proxy
56 - // by type, host, and port only.
57 - private const SOCKS_PROXY_CREDENTIAL_REUSE_VERSION = '7.69.0';
58 - private const PROXY_HEADER_SEPARATION_VERSION = '7.37.0';
59 - /**
60 - * @var array{version: string, features: int}|false|null
61 - */
62 - private static $versionInfo;
63 - private function __construct()
64 - {
65 - }
66 - public static function supportsCurlHandler() : bool
67 - {
68 - $version = self::getVersion();
69 - return $version !== null && \version_compare($version, self::MIN_VERSION, '>=');
70 - }
71 - public static function supportsTls12() : bool
72 - {
73 - $version = self::getVersion();
74 - return self::supportsSsl() && \defined('CURL_SSLVERSION_TLSv1_2') && $version !== null && \version_compare($version, self::TLS_12_VERSION, '>=');
75 - }
76 - public static function supportsTls13() : bool
77 - {
78 - $version = self::getVersion();
79 - return self::supportsSsl() && \defined('CURL_SSLVERSION_TLSv1_3') && $version !== null && \version_compare($version, self::TLS_13_VERSION, '>=');
80 - }
81 - public static function supportsHttp2() : bool
82 - {
83 - $versionInfo = self::getVersionInfo();
84 - return self::supportsTls12() && \defined('CURL_VERSION_HTTP2') && $versionInfo !== null && 0 !== (\CURL_VERSION_HTTP2 & $versionInfo['features']);
85 - }
86 - public static function supportsMultiplex() : bool
87 - {
88 - $version = self::getVersion();
89 - return \defined('CURLOPT_PIPEWAIT') && $version !== null && \version_compare($version, self::MULTIPLEX_VERSION, '>=');
90 - }
91 - public static function supportsHttpVersionReuseMatching() : bool
92 - {
93 - $version = self::getVersion();
94 - if ($version === null || \version_compare($version, self::HTTP_VERSION_REUSE_MATCH_VERSION, '<')) {
95 - return \false;
96 - }
97 - return \version_compare($version, self::HTTP_VERSION_REUSE_MATCH_REGRESSION, '<') || \version_compare($version, self::HTTP_VERSION_REUSE_MATCH_RESTORED, '>=');
98 - }
99 - public static function supportsConnectionCaps() : bool
100 - {
101 - $version = self::getVersion();
102 - return \defined('CURLMOPT_MAX_HOST_CONNECTIONS') && \defined('CURLMOPT_MAX_TOTAL_CONNECTIONS') && $version !== null && \version_compare($version, self::CONNECTION_CAP_VERSION, '>=');
103 - }
104 - public static function ensureConnectionCapsSupported(string $option) : void
105 - {
106 - if (self::supportsConnectionCaps()) {
107 - return;
108 - }
109 - throw new \InvalidArgumentException(\sprintf('The "%s" option requires PHP cURL support for CURLMOPT_MAX_HOST_CONNECTIONS and CURLMOPT_MAX_TOTAL_CONNECTIONS with libcurl %s or newer.', $option, self::CONNECTION_CAP_VERSION));
110 - }
111 - public static function supportsRequiredMultiplex() : bool
112 - {
113 - $version = self::getVersion();
114 - return \defined('CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE') && $version !== null && self::supportsHttp2() && \version_compare($version, self::REQUIRED_MULTIPLEX_VERSION, '>=');
115 - }
116 - public static function supportsHttpsProxy() : bool
117 - {
118 - $versionInfo = self::getVersionInfo();
119 - // CURL_VERSION_HTTPS_PROXY is not defined on every supported PHP
120 - // version; fall back to the curl.h bit value.
121 - $httpsProxyFeature = \defined('CURL_VERSION_HTTPS_PROXY') ? \CURL_VERSION_HTTPS_PROXY : 1 << 21;
122 - return $versionInfo !== null && \version_compare($versionInfo['version'], self::HTTPS_PROXY_VERSION, '>=') && 0 !== ($httpsProxyFeature & $versionInfo['features']);
123 - }
124 - public static function supportsNtlm() : bool
125 - {
126 - $versionInfo = self::getVersionInfo();
127 - // CURL_VERSION_NTLM is not defined on every supported PHP version; fall
128 - // back to the curl.h bit value.
129 - $ntlmFeature = \defined('CURL_VERSION_NTLM') ? \CURL_VERSION_NTLM : 1 << 4;
130 - return \defined('CURLAUTH_NTLM') && $versionInfo !== null && 0 !== ($ntlmFeature & $versionInfo['features']);
131 - }
132 - public static function supportsHandlerSharing() : bool
133 - {
134 - $version = self::getVersion();
135 - return $version !== null && \version_compare($version, self::HANDLER_SHARING_VERSION, '>=');
136 - }
137 - public static function ensureHandlerSharingSupported() : void
138 - {
139 - if (!self::supportsHandlerSharing()) {
140 - throw new \InvalidArgumentException(\sprintf('The "transport_sharing" option requires libcurl %s or higher for cURL share handles.', self::HANDLER_SHARING_VERSION));
141 - }
142 - }
143 - public static function supportsSslSessionSharing() : bool
144 - {
145 - $version = self::getVersion();
146 - return self::supportsSsl() && $version !== null && \version_compare($version, self::SSL_SESSION_SHARING_VERSION, '>=');
147 - }
148 - public static function ensureSslSessionSharingSupported() : void
149 - {
150 - if (!self::supportsSslSessionSharing()) {
151 - throw new \InvalidArgumentException(\sprintf('The "transport_sharing" option requires libcurl %s or higher with SSL support for SSL session sharing.', self::SSL_SESSION_SHARING_VERSION));
152 - }
153 - }
154 - public static function supportsShareConnectionCaches() : bool
155 - {
156 - $version = self::getVersion();
157 - // An undetectable libcurl version is treated as capable so the
158 - // opaque share safeguards fail closed.
159 - return $version === null || \version_compare($version, self::SHARE_CONNECTION_CACHE_VERSION, '>=');
160 - }
161 - public static function supportsProxyTlsCredentialAwareConnectionReuse() : bool
162 - {
163 - $version = self::getVersion();
164 - return $version !== null && \version_compare($version, self::PROXY_TLS_CREDENTIAL_REUSE_VERSION, '>=');
165 - }
166 - public static function supportsProxyCredentialAwareConnectionReuse() : bool
167 - {
168 - $version = self::getVersion();
169 - return $version !== null && \version_compare($version, self::PROXY_CREDENTIAL_REUSE_VERSION, '>=');
170 - }
171 - public static function supportsSocksProxyCredentialAwareConnectionReuse() : bool
172 - {
173 - $version = self::getVersion();
174 - return $version !== null && \version_compare($version, self::SOCKS_PROXY_CREDENTIAL_REUSE_VERSION, '>=');
175 - }
176 - public static function supportsProxyHeaderSeparation() : bool
177 - {
178 - $version = self::getVersion();
179 - return $version !== null && \version_compare($version, self::PROXY_HEADER_SEPARATION_VERSION, '>=') && \defined('CURLOPT_PROXYHEADER') && \defined('CURLOPT_HEADEROPT') && \defined('CURLHEADER_SEPARATE');
180 - }
181 - private static function supportsSsl() : bool
182 - {
183 - $versionInfo = self::getVersionInfo();
184 - return \defined('CURL_VERSION_SSL') && $versionInfo !== null && 0 !== (\CURL_VERSION_SSL & $versionInfo['features']);
185 - }
186 - public static function getVersion() : ?string
187 - {
188 - $versionInfo = self::getVersionInfo();
189 - return $versionInfo === null ? null : $versionInfo['version'];
190 - }
191 - /**
192 - * @return array{version: string, features: int}|null
193 - */
194 - private static function getVersionInfo() : ?array
195 - {
196 - if (self::$versionInfo === null) {
197 - if (!\function_exists('curl_version')) {
198 - self::$versionInfo = \false;
199 - } else {
200 - $versionInfo = \curl_version();
201 - self::$versionInfo = \is_array($versionInfo) && isset($versionInfo['version'], $versionInfo['features']) && \is_string($versionInfo['version']) && \is_int($versionInfo['features']) ? ['version' => $versionInfo['version'], 'features' => $versionInfo['features']] : \false;
202 - }
203 - }
204 - return self::$versionInfo === \false ? null : self::$versionInfo;
205 - }
206 -}